2016-03-24 16 views
1

Geçerli kullanıcı arayüzünü (örneğin bir metin kutusu) iş parçacığımda işlenen bir değere güncellemek için geçmişte delegeler kullandım. async ve await'un sizin için bununla ilgilendiği varsayımı altındaydım.Neden Await sonra kod UI iş parçacığı üzerinde çalışmaz?

Düğmeye basıldığında, aşağıdaki kodu çalıştırdığımda 100 ms'de 100'e kadar çıkacak yeni bir görev başlatın. sayım UI üzerinde görüntülenen, ancak bunun yerine bir TargetInvocationException olsun edilmelidir:

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
     textBox1.Text = "Press button"; 
    } 

    private async void button1_Click(object sender, EventArgs e) 
    { 
     await Task1(); 
    } 

    private Task Task1() 
    { 
     return Task.Factory.StartNew(() => CountMethod()); 
    } 

    private void CountMethod() 
    { 
     for (int i = 0; i < 100; i++) 
     { 
      Task.Delay(100).Wait(); 
      //Console.WriteLine(i.ToString()); 
      textBox1.Text = i.ToString(); 
     } 
    } 
} 
+2

'textBox1.Text = ...' kodu '' beklemeden '' değil. –

cevap

9

sorun UI erişmek için bir iş parçacığı havuzu iş parçacığı kullanarak olmasıdır. Bunu, Task.Factory.StartNew yöntemini kullanarak yapıyorsunuz. İşte

bunu çözebilirsiniz nasıl:

private async Task Task1() 
{ 
    for (int i = 0; i < 100; i++) 
    { 
     await Task.Delay(100); 

     textBox1.Text = i.ToString(); 
    } 
} 

await yüzden şimdiki SynchronizationContext çekeceği anlamına asenkron beklemeye tamamlandıktan sonra, UI iş parçacığı üzerinde yürütür takip kodu. Bu doğrudur, çünkü await UI iş parçacığı tarafından çağrıldı (örneğimde).

Geçerli kodunuzda, bir iş parçacığı havuzu iş parçacığında await çağrılır. Bu durumda geçerli SynchronizationContext boştur ve bu nedenle asenkron beklemeyi izleyen kod ayrıca bir iş parçacığı havuzu iş parçacığı üzerinde yürütülecektir.

+0

Peki, anahtar kelime, işlendikten sonra bir iş parçacığına benzer bir şey yapmayı bekliyor mu? – user3363744

+0

Ne zaman uyumsuzluk üzerinde görev havuzu Task.Factory.StartNew kullanın ve beklemek? – user3363744

+5

@ user3363744: Hayır, "async", çoklu iş parçacığının karşıtıdır - * daha * * yerine * daha az * iş parçacığı kullanır. İş parçacığı havuzunu ('Task.Run',' StartNew' değil) kullanırsanız, CPU'yla ilişkili işiniz varsa, UI iş parçacığı için hareket etmeniz gerekir. –

İlgili konular