Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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#_Multithreading_Exception_Exception Handling - Fatal编程技术网

C# 将异常从线程发送到主线程?

C# 将异常从线程发送到主线程?,c#,multithreading,exception,exception-handling,C#,Multithreading,Exception,Exception Handling,我想将一个异常从当前线程(该线程不是主线程)传递到主线程。 为什么?因为我在另一个线程中检查我的硬锁(该线程使用计时器进行检查),当硬锁不可访问或无效时,我创建一个由我自己定义的异常,然后抛出该异常。 所以这个例外不起作用;(在不知道其他情况的情况下,如果您需要一个线程来确保您的锁不会被持有太长时间或无效,那么您的锁似乎被破坏了 如果确实需要向主线程抛出异常,请设置一个从所有“工作线程”到“主线程”的通信队列,并将整个工作线程包装在一个异常处理程序中,该异常处理程序只会将异常附加到队列中,然后杀

我想将一个异常从当前线程(该线程不是主线程)传递到主线程。 为什么?因为我在另一个线程中检查我的硬锁(该线程使用计时器进行检查),当
硬锁
不可访问或无效时,我创建一个由我自己定义的异常,然后抛出该异常。

所以这个例外不起作用;(

在不知道其他情况的情况下,如果您需要一个线程来确保您的锁不会被持有太长时间或无效,那么您的锁似乎被破坏了


如果确实需要向主线程抛出异常,请设置一个从所有“工作线程”到“主线程”的通信队列,并将整个工作线程包装在一个异常处理程序中,该异常处理程序只会将异常附加到队列中,然后杀死该线程。主线程可以轮询队列以发现异常选项并重新启动在更正错误条件后死机的线程。

将对主窗体执行上下文的引用传递给线程(通过委托或字段)。然后调用方法(send或post)通过引发异常的线程的同步上下文。执行上下文将确保它由ui线程处理。

最好的办法是用
任务替换
线程
(在.NET 4.0中新增).Task
类处理异常的正确封送,无论线程检查任务的结果是什么


如果无法使用.NET 4.0,则来自的CoreEx.dll将包含一个保留异常调用堆栈的
异常.prepareForeTrow
扩展方法。您可以将此方法与MaLio建议的
同步上下文
结合使用,将异常封送到另一个线程。

您可能会发现它更简单将异常处理保持在线程内,并通过在回调中返回
MyException.ToString()
来传回异常消息和堆栈跟踪。当我从另一个线程获得异常时,我要查找的所有内容都在该字符串中。

只有我的2美分

我认为如果您正在运行Windows窗体,则可以在主窗体上使用Invoke、BeginInvoke从try/catch块发送异常。或者您可以在主线程中创建事件处理程序/委托,并通过该事件处理程序/委托将异常发送到主线程,以便主线程中的方法可以处理它。老实说,您没有尝试过这些解决方案,但这是我的第一个想法

另外,可能在主线程上创建WorkerQueue也是一个选项。它将作为backgroundWorker运行,当它收到新的异常发送时,它会相应地进行处理……如果您感兴趣,我可以给您一些小例子

编辑:

在Initialize()中或主线程启动的任何位置:

   Backgroundworker bw = new Backgroundworker();
   bw.DoWork+= jobQueue.Run;
   bw.StartAsync();
    //m_jobQueue = new JobQueue();
    //    new Thread(new ThreadStart(jobQueue.Run)).Start(); 
要发送异常,请使用:

   m_jobQueue.AddJob(StackOverflowException);
到访:

    m_jobQueue.StopJobQueue();

您可以将异常用作事件中的参数。
并在将异常发送到其他线程后进行处理。
代码示例

public delegate void SendToMainDel(string threadName,Exception ex);
public event SendToMainDel SendToMainEv;

public void MySecondThread()
{
    try
    {
    ....
    }catch(Exception ex)
    {
         if(SendToMainEv!=null)
            SendToMainEv("MySecondThread",ex);
    }
}

...
    SendToMainEv += ReceiveOtherThreadExceptions;
...

public void ReceiveOtherThreadExceptions(string threadName,Exception ex)
{ 
   if(InvokeRequired)
   {
      BeginInvoke(new SendToMainDel(ReceiveOtherThreadExceptions), threadName, ex);
      return;
   }

   //there you can handle the exception
   //throw ex;
}

我可以在program.cs中使用
公共静态方法
,并从另一个线程调用它(因为它是静态类),并使用
应用程序终止应用程序。退出
,但这只适用于终止应用程序
而不是执行任何其他操作!那么你怎么说呢!任何描述线程并在线程之间通信的好站点都是你从未分配
默认作业
(或者我遗漏了什么?),它的作用是什么?一个简单的线程替换方法。Sleep
就是使用AutoResetEvent(甚至可以在Windows Mobile上使用)。创建一个新的
AutoResetEvent
,执行
while(pendingJobs.Count>0){job=pendingJobs.Dequeue();}
,如果一个新作业在出列时排队,请在另一个while中放入
resetEvent.WaitOne
而不是Thread.Sleep。在
Enqueue
中,您可以执行
resetEvent.Set()
Run()中唤醒该作业
。嗨,帕特里克!你说得对。为了简单起见,我基本上只是从我的项目中复制了它,删除了大部分代码。我的不好。但至少作为一个例子,我认为它可以。谢谢你指出这些要点。
    m_jobQueue.StopJobQueue();
public delegate void SendToMainDel(string threadName,Exception ex);
public event SendToMainDel SendToMainEv;

public void MySecondThread()
{
    try
    {
    ....
    }catch(Exception ex)
    {
         if(SendToMainEv!=null)
            SendToMainEv("MySecondThread",ex);
    }
}

...
    SendToMainEv += ReceiveOtherThreadExceptions;
...

public void ReceiveOtherThreadExceptions(string threadName,Exception ex)
{ 
   if(InvokeRequired)
   {
      BeginInvoke(new SendToMainDel(ReceiveOtherThreadExceptions), threadName, ex);
      return;
   }

   //there you can handle the exception
   //throw ex;
}