Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.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_Events - Fatal编程技术网

C# 如果创建了一个对象,并在一个线程中分配了事件,然后从另一个线程运行,那么该事件在哪个线程上运行?

C# 如果创建了一个对象,并在一个线程中分配了事件,然后从另一个线程运行,那么该事件在哪个线程上运行?,c#,.net,events,C#,.net,Events,如果我在主UI线程中创建一个对象,然后从另一个线程调用该对象中的一个方法,那么引发的任何事件会在单独的线程或主UI线程中运行吗 例如: WebClient client = new WebClient(); client.DownloadDataCompleted += new DownloadDataCompletedEventHandler( delegate(object sender, DownloadDataCompletedEventArgs e) {

如果我在主UI线程中创建一个对象,然后从另一个线程调用该对象中的一个方法,那么引发的任何事件会在单独的线程或主UI线程中运行吗

例如:

WebClient client = new WebClient();
client.DownloadDataCompleted += new DownloadDataCompletedEventHandler(
    delegate(object sender, DownloadDataCompletedEventArgs e)
    {
        Thread.Sleep(60000);
    });
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(
    delegate(object sender, DoWorkEventArgs e)
    {
        Thread.Sleep(60000);
        client.DownloadDataAsync("http://www.example.com");
    });
worker.RunWorkerAsync();
将事件连接到他们自己的方法而不是代理会有什么不同吗


谢谢。

事件在调用它的线程上同步引发,也就是说,事件的所有订阅服务器都在引发事件的线程中运行

您还可以通过BeginInvoke异步引发事件,在这种情况下,我相信它最终会由应用程序线程池中的线程处理

您需要保护与任何UI组件交互的任何处理程序,以防在主UI线程之外的单独线程上执行


您可以通过Control.invokererequired/Control.Invoke(…)技术来实现这一点,

事件处理程序与任何其他方法一样,在调用它们的线程上运行。但是,如果处理程序是在实现
ISynchronizeInvoke
(例如winforms控件)的类上定义的,则可以在创建它的线程上调用它。下面是一个用于引发事件的扩展方法,它会自动处理此问题:

    /// <summary>
    /// Fires an event and catches any exceptions raised by an event handler.
    /// </summary>
    /// <param name="ev">The event handler to raise</param>
    /// <param name="sender">The sender of the event.</param>
    /// <param name="e">Event arguments for the event.</param>
    /// <typeparam name="T">The type of the event args.</typeparam>
    public static void Fire<T>(this EventHandler<T> ev, object sender, T e) where T : EventArgs
    {
        if (ev == null)
        {
            return;
        }

        foreach (Delegate del in ev.GetInvocationList())
        {
            try
            {
                ISynchronizeInvoke invoke = del.Target as ISynchronizeInvoke;
                if (invoke != null && invoke.InvokeRequired)
                {
                    invoke.Invoke(del, new[] { sender, e });
                }
                else
                {
                    del.DynamicInvoke(sender, e);
                }
            }
            catch (TargetInvocationException ex)
            {
                ex.InnerException.PreserveStackTrace();
                throw ex.InnerException;
            }
        }
    }

    /// <summary>
    /// Called on a <see cref="TargetInvocationException"/> to preserve the stack trace that generated the inner exception.
    /// </summary>
    /// <param name="e">The exception to preserve the stack trace of.</param>
    public static void PreserveStackTrace(this Exception e)
    {
        var ctx = new StreamingContext(StreamingContextStates.CrossAppDomain);
        var mgr = new ObjectManager(null, ctx);
        var si = new SerializationInfo(e.GetType(), new FormatterConverter());

        e.GetObjectData(si, ctx);
        mgr.RegisterObject(e, 1, si);
        mgr.DoFixups();
    }
//
///激发事件并捕获事件处理程序引发的任何异常。
/// 
///要引发的事件处理程序
///事件的发送者。
///事件的事件参数。
///事件args的类型。
publicstaticvoidfire(此EventHandler ev,objectsender,te),其中T:EventArgs
{
如果(ev==null)
{
返回;
}
foreach(ev.GetInvocationList()中的委托del)
{
尝试
{
ISynchronizeInvoke=del.Target作为ISynchronizeInvoke;
if(invoke!=null&&invoke.invokererequired)
{
invoke.invoke(del,new[]{sender,e});
}
其他的
{
del.DynamicInvoke(发送方,e);
}
}
捕获(目标异常)
{
ex.InnerException.PreserveStackTrace();
抛出ex.InnerException;
}
}
}
/// 
///调用以保留生成内部异常的堆栈跟踪。
/// 
///保留的堆栈跟踪的异常。
公共静态跟踪(此异常为e)
{
var ctx=新StreamingContext(StreamingContextState.CrossAppDomain);
var mgr=newobjectmanager(null,ctx);
var si=new SerializationInfo(例如GetType(),new FormatterConverter());
e、 GetObjectData(si、ctx);
经理注册对象(e、1、si);
经理DoFixups();
}
编辑:保留StackTrace并不是这个问题答案的一部分,它只是我使用的解决方案的一部分。实际上,我是从另一个答案中得到这个方法的,所以,我不记得确切的答案是从哪里来的,但它的功劳确实属于其他人。对不起,我不记得是谁了