Winforms我应该多线程还是使用事件计时器?

时间:2009-03-05 16:12:58

标签: c# winforms multithreading user-interface

我目前有一个线程,它从网络中侦听数据,然后在其上运行规则。然后我想将数据传递给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();

  }

6 个答案:

答案 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)

是不是更容易抛出一个代表谁举起一个事件来告知表单刷新自己?