我目前有一个线程,它从网络中侦听数据,然后在其上运行规则。然后我想将数据传递给GUI。我担心GUI中出现死锁。我无法弄清楚将互斥体放在GUI端。我也在使用c#和dotnet 3.5。
我想出的是 1)使用计时器创建事件并转储线程。担心表现。 2)使用中间事件将数据复制到GUI。 3)深入研究并找出使用GUI的线程安全方式。
您认为最佳方式是什么?
编辑:这是我正在使用的解决方案。我传入更改的元素,然后使用互斥锁保护大对象。我使用helper函数来使用InvokeRequired切换线程,然后使用委托来切换BeginInvoke。从阅读答案然后跟随链接拉出来,直到Threading in Windows Forms到达Jon Skeet。
delegate void UInt32ParameterDelegate(UInt32 n);
public void UpdateLocation(UInt32 n)
{
if (InvokeRequired)
{
// We're not in the UI thread, so we need to call BeginInvoke
BeginInvoke(new UInt32ParameterDelegate(UpdateLocation), new object[] { n });
return;
}
// Must be on the UI thread if we've got this far
this.engine.location.UpdateBusy.WaitOne();
// do the work in here
this.engine.location.UpdateBusy.ReleaseMutex();
}
答案 0 :(得分:3)
我希望我能正确理解你的问题。
后台线程读取数据并执行任何操作后,应使用Invoke
调用GUI线程上的方法。该方法将更新应在GUI中更新的任何内容。
答案 1 :(得分:3)
Windows窗体中的同步非常简单。您可以在后台线程中调用Control.Invoke()。线程将停止,直到委托在UI线程上运行完毕。根本不需要同步。
如果停止线程是个问题,请使用Control.BeginInvoke()。如果线程在继续运行时可能会改变它们,则必须使用锁保护传递给委托的对象。在生产者 - 消费者场景中很少出现这种情况,线程可以简单地创建新对象。
请确保您不经常调用()。比每秒大约1000次更频繁地执行它,并且UI线程将停止抽取Windows消息,因为处理调用请求而陷入困境。因为它是你想要取悦的人眼,每秒调用超过25次只是浪费精力。池中间导致集合对象。
答案 2 :(得分:2)
从不在GUI线程上从网络中读取。在网络中断期间运行应用程序并且GUI因此挂起,这只是时间问题。这会让您的用户感到沮丧。
在您的情况下,我认为最好的方法是让后台线程完成读取操作。然后获取结果数据并通过SynchronizationContext Post或Send方法将其移回GUI线程。
答案 3 :(得分:1)
您应该只将一个事件从您的网络线程传递到您的UI线程。
然后使用begininvoke交叉线程,这样就不会出现交叉线程异常。
Need help getting info across a UI thread and another thread in C#
答案 4 :(得分:1)
您可以使用backgroundworker来处理后台线程中的数据引导,一旦完成,您可以结束后台工作,触发它的RunWorkerCompletedEventHandler。在RunWorkerCompletedEventHandler中,您可以使用结果更新GUI线程。
答案 5 :(得分:0)
是不是更容易抛出一个代表谁举起一个事件来告知表单刷新自己?