Bạn là đúng, nó không phải là tốt để vượt qua điều khiển để đề. Điều khiển Winforms là đơn luồng, chuyển chúng đến nhiều chủ đề có thể gây ra điều kiện chủng tộc hoặc phá vỡ giao diện người dùng của bạn. Thay vào đó, bạn nên làm cho các tính năng của thread của bạn có sẵn cho giao diện người dùng và để cho nó gọi thread khi giao diện người dùng là tốt và sẵn sàng. Nếu bạn muốn có chủ đề nền kích hoạt thay đổi giao diện người dùng, hãy hiển thị sự kiện nền và đăng ký sự kiện đó từ giao diện người dùng. Chủ đề có thể kích hoạt các sự kiện bất cứ khi nào nó muốn và giao diện người dùng có thể phản hồi chúng khi có thể.
Tạo giao tiếp hai chiều giữa các chủ đề không chặn chuỗi giao diện người dùng là rất nhiều công việc. Dưới đây là một ví dụ viết tắt đánh giá cao bằng một lớp BackgroundWorker:
public class MyBackgroundThread : BackgroundWorker
{
public event EventHandler<ClassToPassToUI> IWantTheUIToDoSomething;
public MyStatus TheUIWantsToKnowThis { get { whatever... } }
public void TheUIWantsMeToDoSomething()
{
// Do something...
}
protected override void OnDoWork(DoWorkEventArgs e)
{
// This is called when the thread is started
while (!CancellationPending)
{
// The UI will set IWantTheUIToDoSomething when it is ready to do things.
if ((IWantTheUIToDoSomething != null) && IHaveUIData())
IWantTheUIToDoSomething(this, new ClassToPassToUI(uiData));
}
}
}
public partial class MyUIClass : Form
{
MyBackgroundThread backgroundThread;
delegate void ChangeUICallback(object sender, ClassToPassToUI uiData);
...
public MyUIClass
{
backgroundThread = new MyBackgroundThread();
// Do this when you're ready for requests from background threads:
backgroundThread.IWantTheUIToDoSomething += new EventHandler<ClassToPassToUI>(SomeoneWantsToChangeTheUI);
// This will run MyBackgroundThread.OnDoWork in a background thread:
backgroundThread.RunWorkerAsync();
}
private void UserClickedAButtonOrSomething(object sender, EventArgs e)
{
// Really this should be done in the background thread,
// it is here as an example of calling a background task from the UI.
if (backgroundThread.TheUIWantsToKnowThis == MyStatus.ThreadIsInAStateToHandleUserRequests)
backgroundThread.TheUIWantsMeToDoSomething();
// The UI can change the UI as well, this will not need marshalling.
SomeoneWantsToChangeTheUI(this, new ClassToPassToUI(localData));
}
void SomeoneWantsToChangeTheUI(object sender, ClassToPassToUI uiData)
{
if (InvokeRequired)
{
// A background thread wants to change the UI.
if (iAmInAStateWhereTheUICanBeChanged)
{
var callback = new ChangeUICallback(SomeoneWantsToChangeTheUI);
Invoke(callback, new object[] { sender, uiData });
}
}
else
{
// This is on the UI thread, either because it was called from the UI or was marshalled.
ChangeTheUI(uiData)
}
}
}
Nguồn
2009-01-20 20:08:57
Vui lòng đánh dấu một câu trả lời như được chấp nhận nếu một giải quyết vấn đề của bạn. – SandRock