2014-09-09 18 views
5

Yapmam gereken 10 görevim olduğu bir windows form projesi geliştiriyorum ve bunu async şekilde yapmak istiyorum. Bu görevler, kullanıcı bir düğmeyi tıklattığında yıldız olacak ve bunu yapmak için async yöntemini çağırıyorum. Kodumda, zaten bu işlemler için bir parametre listesi var.Bir async yönteminde kullanıcı arabirimine nasıl geri bildirim sağlanabilir?

Sorularım ise:

A) Nasıl paralel tüm süreci çalıştırmak için kodumu dönüşümü? (Ben uyumsuzluk/beklemeyi uygulamak istiyorum)

B) UI uygulamasına nasıl geri bildirim sağlanabilir?

kod feryat denedim budur:

Benim düğmesi parametresini

private async void ProcessObject(ProcessViewModel process) 
{ 
    // this is my loop scope, which I need to run in parallel 
    { 
     // my code is here 

     // increment the progress of this process 
     process.Progress++; 

     // feedback to UI (accessing the UI controls) 
     UpdateRow(process); 
    } 
} 
alma benim sürecini simüle etmek süreçleri
private void button1_Click(object sender, EventArgs e) 
{ 
    // almost 15 process 
    foreach (var process in Processes) 
    { 
     // call a async method to process 
     ProcessObject(process); 
    } 
} 

yöntem başlatmak için bir yöntemi çağırmak için

Bunu denedim, ancak UI'm (bir kılavuz) güncellemenin doğru yolu olup olmadığından emin değilim. İçinde atılan istisnalar fark olmayacak çünkü her şeyden önce

private void UpdateRow(ProcessViewModel process) 
{ 
    dataGridView1.Rows[process.Index - 1].Cells[1].Value = process.Progress; 
    dataGridView1.Refresh(); 
} 
+0

'ProcessObject''ü beklemiyorsunuz. Yazım hatası mı? –

+0

Hayır, yalnızca ProcessObject yöntemini arıyorum. Bu yöntem için bir sonucum yok, beklemek için onu değiştirmeli miyim? –

+0

Bu, TPL ile de yapılabilir: http://stackoverflow.com/questions/16913560/want-to-use-task-parallel-library-with-progress-reporting-for-updating-database – Schwarzie2478

cevap

6

, (Olay işleyicileri istisnalar) hiçbirasync void yöntemleri söylüyorlar. Bunun yerine async Task kullanın ve bekleyin. o bir sonraki başlayacak bittikten sonra

private async void button1_Click(object sender, EventArgs e)// <--Note the async modifier 
{ 
    // almost 15 process 
    foreach (var process in Processes) 
    { 
     // call a async method to process 
     await ProcessObject(process); 
    } 
} 

private async Task ProcessObject(ProcessViewModel process)// <--Note the return type 
{ 
    // my code is here with some loops 
    await Task.Run(()=> 
    { 
     //Will be run in ThreadPool thread 
     //Do whatever cpu bound work here 
    }); 

    //At this point code runs in UI thread 
    process.Progress++; 

    // feedback to UI 
    UpdateRow(process); 
} 

Ancak bu, bir seferde sadece bir görevi başlayacaktır. Hepsini bir kerede başlatmak isterseniz, bunları başlatmak için Task.WhenAll'u kullanabilirsiniz.

private async void button1_Click(object sender, EventArgs e)// <--Note the async modifier 
{ 
    var tasks = Processes.Select(ProcessObject).ToList(); 
    await Task.WhenAll(tasks); 
} 
+0

Bu işlem yönteminde bir döngüye sahip olacağım için, Task.Run içinde UpdateRow çağrısı yapmam gerekiyor. Burada denedim, ancak başka bir iş parçacığı tarafından oluşturulduğu için DataGridView denetimimin iş parçacığı tarafından erişilebileceğini söyleyen bir hata alıyorum.Parametremde dataGridView referansını geçmeye çalıştım ama işe yaramıyor, bunu nasıl çözebilirim? Anwser –

+0

için teşekkürler Anonim –

+0

içinde bazı düzenlemeler yaptım Eğer orijinal posta kodu sakıncası yoksa. Kodunuza göre cevap verdim, ama şimdi 'Task.Run' içinde' UpdateRow' kullanmanız gerektiğini söylüyorsunuz. Bu işe yaramaz. Ana iş parçasında çağrılmalıdır. Ayrıca neden orada bir döngüye ihtiyacınız var? Daha fazla bilgi verin lütfen. –

8

Sriram'den ancak sana bir üs olarak onun cevabını kullanarak UI iş parçacığı üzerinde ilerlemeyi güncelleştirmek için başka bir yol göstermek istedim,/asenk yapmak in his answer beklemek üzere nasıl kaplı.

.NET 4.5 IProgress<T> arabirimini ve Progress<T> sınıfını ekledi. Yerleşik İlerleme sınıfı, senkronizasyon bağlamını yakalar, tıpkı async/await gibi, ilerlemenizi bildirmeye gittiğinizde, geri çağrısını yapmak için bu bağlamı kullanır (sizin durumunuzdaki UI iş parçacığı).

private async void button1_Click(object sender, EventArgs e) 
{ 
    var progress = new Progress<ProcessViewModel>(UpdateRow); //This makes a callback to UpdateRow when progress is reported. 

    var tasks = Processes.Select(process => ProcessObject(process, progress)).ToList(); 
    await Task.WhenAll(tasks); 
} 

private async Task ProcessObject(ProcessViewModel process, IProgress<ProcessViewModel> progress) 
{ 
    // my code is here with some loops 
    await Task.Run(()=> 
    { 
     //Will be run in ThreadPool thread 
     //Do whatever cpu bound work here 


     //Still in the thread pool thread 
     process.Progress++; 

     // feedback to UI, calls UpdateRow on the UI thread. 
     progress.Report(process); 
    }); 
} 
+0

Scott: Bunu düşündüm, ama async metodunda bu biraz yararlı. Async yöntemi devam ettirildiğinde, 'ProcessRbject' içinde' UpdateRow' doğrudan aranabilir. –

+0

@SriramSakthivel Sizin yönteminizin daha iyi bir yöntem olduğunu kabul ediyorum (bu yüzden cevabım, cevabımda bahsettiğim ilk şeydir), ancak OP buna karşı dayanıklı görünüyordu, sadece diğer seçenekleri vermek istedim –

+1

Ummm, +1 sizin için diğer Seçenek :) –

İlgili konular