2009-03-05 82 views
2

我目前有一个线程可以侦听来自网络的数据,然后在其上运行规则。然后我想将数据传递给GUI。我担心在GUI中发生死锁。我无法弄清楚把互斥体放在GUI一边。我也使用c#和dotnet 3.5。Winforms应该我多线程或使用事件计时器?

我想到的是 1)使用计时器来创建事件并转储线程。担心表现。 2)使用中间事件将数据复制到GUI。 3)挖掘并找出使用GUI的线程安全方式。

您认为最好的方法是什么?

编辑:这是我正在使用的解决方案。我传入更改后的元素,然后用互斥锁保护大对象。我使用帮助函数切换线程使用InvokeRequired然后BeginInvoke与委托。从阅读答案拉动,然后跟随链接,直到达到Threading in Windows FormsJon 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

您使用.net 2.0吗? – JoshBerke 2009-03-05 16:15:34

回答

3

Windows窗体中的同步非常简单。您可以在后台线程中调用Control.Invoke()。线程将停止运行,直到委托在UI线程上完成运行。根本不需要同步。

如果拖延线程是一个问题,请使用Control.BeginInvoke()。如果线程在继续运行时可能会改变它,则必须使用锁来保护传递给委托的对象。在生产者 - 消费者场景中情况很少,线程可以简单地创建新对象。

确保您不经常调用()。更频繁地执行此操作的次数超过每秒约1000次,并且UI线程将停止泵送Windows消息,并因处理调用请求而陷入停滞状态。由于它是你想讨好的人类眼睛,每秒调用超过25次以上就是浪费精力。池中间结果集合对象。

+0

+1,可以很好地解答Windows窗体中的同步问题。 – 2012-10-19 00:18:41

0

只是抛出一个委托人提出事件通知表单刷新自己不容易吗?

2

从不在GUI线程上从网络读取。在网络中断期间运行应用程序只是时间问题,因此GUI会挂起。这会让你的用户感到非常失望。

在你的情况下,我认为最好的办法是让后台线程完成读取操作。然后获取结果数据并通过SynchronizationContext Post或Send方法将其移回GUI线程。

3

我希望我能正确理解你的问题。

在后台线程读取数据并执行任何想要的操作后,应该使用Invoke在GUI线程上调用方法。该方法会更新GUI中应该更新的任何内容。

1

你可以使用一个backgroundworker将处理在后台线程的datareading并且当它这样做,你可以结束BackgroundWorker的触发它的RunWorkerCompletedEventHandler。在RunWorkerCompletedEventHandler中,您可以使用结果更新您的GUI线程。

相关问题