[VS 2010 Beta与.Net Framework 3.5]
我编写了一个C#组件来异步监视套接字并在收到数据时引发事件。我设置VB表单以在引发事件时显示消息框。我注意到的是,当组件同步引发事件时,消息框会阻止组件代码并锁定表单,直到用户关闭消息。当它异步引发时,它既不会阻塞代码,也不会锁定表单。
我想要的是一种以不会阻塞代码的方式引发事件的方法,但是在与表单相同的线程上调用它(以便它锁定表单直到用户选择一个选项。)
你能救我吗? 感谢。[成分]
using System;
using System.Threading;
using System.ComponentModel;
namespace mySpace
{
public delegate void SyncEventHandler(object sender, SyncEventArgs e);
public delegate void AsyncEventHandler(object sender, AsyncEventArgs e);
public class myClass
{
readonly object syncEventLock = new object();
readonly object asyncEventLock = new object();
SyncEventHandler syncEvent;
AsyncEventHandler asyncEvent;
private delegate void WorkerDelegate(string strParam, int intParam);
public void DoWork(string strParam, int intParam)
{
OnSyncEvent(new SyncEventArgs());
AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(null);
WorkerDelegate delWorker = new WorkerDelegate(ClientWorker);
IAsyncResult result = delWorker.BeginInvoke(strParam, intParam, null, null);
}
private void ClientWorker(string strParam, int intParam)
{
Thread.Sleep(2000);
OnAsyncEvent(new AsyncEventArgs());
OnAsyncEvent(new AsyncEventArgs());
}
public event SyncEventHandler SyncEvent
{
add { lock (syncEventLock) syncEvent += value; }
remove { lock (syncEventLock) syncEvent -= value; }
}
public event AsyncEventHandler AsyncEvent
{
add { lock (asyncEventLock) asyncEvent += value; }
remove { lock (asyncEventLock) asyncEvent -= value; }
}
protected void OnSyncEvent(SyncEventArgs e)
{
SyncEventHandler handler;
lock (syncEventLock) handler = syncEvent;
if (handler != null) handler(this, e, null, null); // Blocks and locks
//if (handler != null) handler.BeginInvoke(this, e, null, null); // Neither blocks nor locks
}
protected void OnAsyncEvent(AsyncEventArgs e)
{
AsyncEventHandler handler;
lock (asyncEventLock) handler = asyncEvent;
//if (handler != null) handler(this, e, null, null); // Blocks and locks
if (handler != null) handler.BeginInvoke(this, e, null, null); // Neither blocks nor locks
}
}
}
[表格]
Imports mySpace
Public Class Form1
Public WithEvents component As New mySpace.myClass()
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
component.DoWork("String", 1)
End Sub
Private Sub component_SyncEvent(ByVal sender As Object, ByVal e As pbxapi.SyncEventArgs) Handles component.SyncEvent
MessageBox.Show("Synchronous event", "Raised:", MessageBoxButtons.OK)
End Sub
Private Sub component_AsyncEvent(ByVal sender As Object, ByVal e As pbxapi.AsyncEventArgs) Handles component.AsyncEvent
MessageBox.Show("Asynchronous event", "Raised:", MessageBoxButtons.OK)
End Sub
End Class
答案 0 :(得分:6)
你需要调用表单的BeginInvoke
方法(仅),它将在表单的UI线程上运行委托(从而阻止表单),而不会阻塞调用线程等待电话结束。
如果您没有对表单实例的引用,则可以从UI线程保存SynchronizationContext.Current
,然后在Post
实例上调用SynchronizationContext
,这将是等效的。
答案 1 :(得分:1)
我建议使用SynchronizationContext.Post
,在委托中传递对话框代码。这不会阻止(其他线程的)代码,但会在UI线程中执行对话框代码,因此它将被阻止。
答案 2 :(得分:0)
是的,您可以使用表单(或任何控件)上的Invoke()
方法在UI线程中以同步方式同步和执行任何委托。
答案 3 :(得分:0)
如果我理解正确,我认为你正在以错误的方式解决问题。
我相信你需要在显示消息框时显式禁用表单上的控件,然后在用户关闭框时重新启用它们。
请澄清;你希望UI线程在显示Box时抽取消息吗? (例如,表格重新绘制)