提高.NET活动主UI线程上 [英] Raise Events in .NET on the main UI thread

查看:157
本文介绍了提高.NET活动主UI线程上的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个类库在.NET中,其他开发者最终消费。此库利用几个工作线程,和,这将导致一些UI这些线程火状态事件控制在的WinForms要更新 / WPF应用程序。

通常情况下,每次更新,你将需要检查的WinForms或同等WPF财产.InvokeRequired财产和调用此用于更新的主UI线程上。这可以老去很快,东西感觉不对有关使年底开发商这样做,所以...

有什么办法,我的图书馆可以发射/调用的事件/从主UI线程代表?

在特定的...


  1. 我应该会自动检测的主线程使用?

  2. 如果不是这样,我应该要求最终开发者调用一些(伪) UseThisThreadForEvents()当应用程序启动,所以我可以抓住从该呼叫目标线程的方法?


解决方案

您图书馆可以检查该事件的调用列表中的每个代表的目标,并且元帅调用目标线程,如果该目标是ISynchronizeInvoke:

 私人无效RaiseEventOnUIThread(代表theEvent,对象[]参数)
{
  的foreach(在theEvent.GetInvocationList委托D())
  {
    ISynchronizeInvoke同步程序= d.Target为ISynchronizeInvoke;
    如果(同步程序== NULL)
    {
      d.DynamicInvoke(参数);
    }
    其他
    {
      syncer.BeginInvoke(D,参数); //省略清理
    }
  }
}

另一种方法,这使得线程合同更加明确,是要求库的客户在ISynchronizeInvoke或SynchronizationContext的传递上,他们希望你能引发事件的线程。这使你的库的用户比偷偷检查委托目标的办法多一点的可视性和控制。

在关于你的第二个问题,我会放在你的线程或OnXxx任何API用户code调用可能导致被引发的事件中编组的东西。

I'm developing a class library in .NET that other developers will consume eventually. This library makes use of a few worker threads, and those threads fire status events that will cause some UI controls to be updated in the WinForms / WPF application.

Normally, for every update, you would need to check the .InvokeRequired property on WinForms or equivalent WPF property and invoke this on the main UI thread for updating. This can get old quickly, and something doesn't feel right about making the end developer do this, so...

Is there any way that my library can fire/invoke the events/delegates from the main UI thread?

In particular...

  1. Should I automatically "detect" the "main" thread to use?
  2. If not, should I require the end developer to call some (pseudo) UseThisThreadForEvents() method when the application starts so I can grab the target thread from that call?

解决方案

Your library could check the Target of each delegate in the event's invocation list, and marshal the call to the target thread if that target is ISynchronizeInvoke:

private void RaiseEventOnUIThread(Delegate theEvent, object[] args)
{
  foreach (Delegate d in theEvent.GetInvocationList())
  {
    ISynchronizeInvoke syncer = d.Target as ISynchronizeInvoke;
    if (syncer == null)
    {
      d.DynamicInvoke(args);
    }
    else
    {
      syncer.BeginInvoke(d, args);  // cleanup omitted
    }
  }
}

Another approach, which makes the threading contract more explicit, is to require clients of your library to pass in an ISynchronizeInvoke or SynchronizationContext for the thread on which they want you to raise events. This gives users of your library a bit more visibility and control than the "secretly check the delegate target" approach.

In regard to your second question, I would place the thread marshalling stuff within your OnXxx or whatever API the user code calls that could result in an event being raised.

这篇关于提高.NET活动主UI线程上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆