2010-05-05 164 views
2

我想基于在后台线程进行轮询在.NET应用停用UI的部分。后台线程检查应用程序使用的全局数据库连接是否仍然可用并且可操作。多线程委托/事件

我需要做的,宁愿做没有在UI线程上投票,是添加一个事件处理程序,可以通过后台线程,如果连接状态的变化而提高。这样,任何表单都可以有一个处理程序,它将禁用需要连接功能的那些UI部分。

试图在保持线的子类使用直事件声明,并在后台线程引发事件引起关于从其它线程访问UI控件跨线程执行错误。

显然,有做这种正确的方式,但我们用有限的事件(单线程应用为主),几乎与代表没有经验。我已经阅读了代表的文档和示例,它似乎更接近我们需要的内容,但我不确定如何在此实例中使其工作。

的应用主要是写在VB.NET,但在C#示例或帮助是没关系。

+0

在DOTNET,你不应该有一个不断打开全局连接。阅读ConnectionPooling。 http://stackoverflow.com/questions/2715714/ – 2010-05-05 22:00:51

+0

@亨克霍尔特曼:如果你不知道他的情况,你不能做出这样的表述。此外,微软在框架中包含的提供商也不推荐使用。 – AMissico 2010-05-05 22:05:11

+0

@amissico:使用我的技巧下面,它并不重要(它同样适用于...) – 2010-05-05 22:07:22

回答

2

可以名帅事件的饲养返回到UI线程。由于这可能(如果你设计的很好)是从一个单独的类中完成的,我的建议是将当前SynchronizationContext的副本传递到处理后台进程的类中。

下面是在C#中的一些示例代码:

public class BackgroundWork 
{ 
    public SynchronizationContext Context { get; private set; } 
    public BackgroundWork(SynchronizationContext context) 
    { 
     this.Context = context; 
    } 

    // Thread handler, etc... 

    // Method to raise event 
    void RaiseEvent() 
    { 
     Context.Post((state) => 
     { 
      // Raise the event 
      this.ConnectionStatusChanged(this, EventArgs.Empty); 
     }, null); 
    } 
} 

然后,当你构建类(在你的UI线程),它传递当前环境:

BackgroundWork worker = new BackgroundWork(SynchronizationContext.Current); // This passes the UI thread context... 
worker.Start(); 

(这由方式,是BackgroundWorker类使用,这就是为什么它的工作原理相同的Windows窗体和WPF相同的技术......)

0

通过使用Control.Dispatcher.Invoke解决跨线程执行错误:

public void EnventHandlerMethod(object sender, EventArgs e) 
{ 
    myLabel.Dispatch.Invoke(new Action(() => { myLabel.Content = "Updated"; })); 
} 

事件处理程序可以根据你处理事件而变化的签名。当然,如果你只是改变另一个线程中的控件,你只需要上述方法的主体。

而且这个(我认为)假设.NET 3.5

+0

这解决了它在客户端订阅端,但不是在连接池端... – 2010-05-05 22:05:52

0

尝试要改变控制,或任何控制的Invoke方法真的,并提供一个小功能,做你想做的工作。或者参见BeginInvoke异步执行。

只是要小心线程问题,更改变量“主”线程改变等

+0

这(几乎)解决了它客户端订阅端,但不在连接池端... – 2010-05-05 22:06:38