Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 异步激发的事件能否在窗体上同步运行?_C#_.net_Vb.net_Asynchronous_Delegates - Fatal编程技术网

C# 异步激发的事件能否在窗体上同步运行?

C# 异步激发的事件能否在窗体上同步运行?,c#,.net,vb.net,asynchronous,delegates,C#,.net,Vb.net,Asynchronous,Delegates,[VS 2010 Beta版与.Net Framework 3.5版] 我编写了一个C#组件,用于异步监视套接字并在接收数据时引发事件。我将VB窗体设置为在引发事件时显示消息框。我注意到,当组件同步引发事件时,消息框会阻止组件代码并锁定表单,直到用户关闭消息。当异步引发时,它既不会阻塞代码,也不会锁定表单 我想要的是一种引发事件的方法,它不会阻止代码,而是在与表单相同的线程上调用(这样它会锁定表单,直到用户选择一个选项) 你能帮我吗? 谢谢 [组件] using System; using Sy

[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
[表格]

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
是的,您可以使用窗体(或任何控件)上的方法在UI线程中以同步方式同步和执行任何委托。

您需要调用窗体的
BeginInvoke
方法(仅限),该方法将在窗体的UI线程上运行委托(从而阻止窗体),不阻塞调用线程以等待调用完成


如果您没有对表单实例的引用,可以从UI线程保存
SynchronizationContext.Current
,然后在
SynchronizationContext
实例上调用
Post
,这将是等效的。

如果我理解正确,我认为您以错误的方式处理问题

我认为无论何时显示消息框,都需要显式禁用表单上的控件,然后在用户关闭消息框时重新启用它们


请澄清;是否希望UI线程在显示框时发送消息?(例如,表单会自动重新绘制)

我建议使用
SynchronizationContext.Post
,在委托中传递对话框代码。这不会阻止(其他线程的)代码,但会在UI线程中执行对话框代码,因此它将被阻止。

我不认为这是他的意思。他想要一种简单的方法来“锁定”表单,但他仍然希望自己的UI线程能够传递消息。无论如何,这就是我读他的问题的方式。
Invoke
将阻止组件代码,我认为OP需要使用
BeginInvoke
在UI线程上执行,但不会阻止组件代码。我尝试使用Invoke()而不是BeginInvoke(),它在表单上工作,但会阻止组件代码。此外,在使用BeginInvoke()调用的方法中调用Invoke()不会改变任何内容。(我在哪里可以找到帖子和评论的格式指南?@cyclotis04-你可以在这里找到一些格式语法,你错了。他需要在UI线程上调用
ShowDialog
。他想让它发送消息,但不响应用户输入。如果我在不使用任何BeginInvoke()的情况下引发事件,则消息框会锁定表单,直到用户做出选择。如果涉及到任何BeginInvoke(),则表单不会锁定。@cyclotis04-我确信SLaks是正确的。关键是你在VB窗体上调用BeginInvoke。如果你调用
委派.BeginInvoke
,你也必须调用
EndInvoke
。既然我理解了他的要求,我相信你是正确的+1好的,我想我理解为什么需要这样做,但我有点困惑如何让它工作。在哪里保存UI线程的上下文,以及如何将其传递给异步线程?将其从UI线程保存到类中的字段中(可能在
DoWork