Tôi có đoạn mã sau trong một ứng dụng WinForms với một nút và một label:Truy cập vào giao diện điều khiển trong Task.Run với async/đang chờ đợi trên WinForms
using System;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private async void button1_Click(object sender, EventArgs e)
{
await Run();
}
private async Task Run()
{
await Task.Run(async() => {
await File.AppendText("temp.dat").WriteAsync("a");
label1.Text = "test";
});
}
}
}
Đây là một phiên bản đơn giản của ứng dụng thực tế tôi m làm việc trên. Tôi đã có ấn tượng rằng bằng cách sử dụng async/await trong số Task.Run
tôi có thể đặt thuộc tính label1.Text
. Tuy nhiên, khi chạy mã này tôi nhận được lỗi rằng tôi không phải trên thread UI và tôi không thể truy cập vào điều khiển.
Tại sao tôi không thể truy cập điều khiển nhãn?
Bạn không nên sử dụng các phương thức void không đồng bộ từ ngữ cảnh đồng bộ hóa GUI. C.f. http://msdn.microsoft.com/en-us/magazine/jj991977.aspx - "Các ứng dụng GUI và ASP.NET có một SynchronizationContext cho phép chỉ một đoạn mã chạy cùng một lúc. Khi chờ đợi hoàn thành, nó sẽ cố gắng để thực thi phần còn lại của phương thức async trong bối cảnh đã capture, nhưng ngữ cảnh đó đã có một luồng trong đó, đó là (đồng bộ) chờ đợi phương thức async hoàn tất. Chúng đang đợi nhau, gây ra bế tắc. " – Daniel
@Daniel Trích dẫn đó là về việc chờ đồng bộ (ví dụ: 'Chờ()') trên mã không đồng bộ và tôi chắc chắn không đề xuất điều đó. Từ cùng một bài báo: “Các phương thức không đồng bộ hóa ngược trở lại có một mục đích cụ thể: để tạo các trình xử lý sự kiện không đồng bộ có thể.” Và đó chính xác là những gì tôi đang làm ở đây. – svick
Cần lưu ý rằng bất kỳ ngoại lệ nào xảy ra trong phương thức 'private async Task Run()' không được xử lý, sẽ "bong bóng" lên đến trình xử lý sự kiện không đồng bộ. – Jaans