Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.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_Events_Exception_Exception Handling - Fatal编程技术网

C# 处理源自线程的错误的标准方法

C# 处理源自线程的错误的标准方法,c#,multithreading,events,exception,exception-handling,C#,Multithreading,Events,Exception,Exception Handling,这个问题已经提过很多次了,但我想再问一次,因为我在这里读到了一些对我来说似乎不正确的东西(可能是因为其中一个与.NET CF有关),我要求验证我认为合理的特定方法,并感谢您的任何反馈 无论如何,这种情况和其他人很相似——我想处理来自线程的错误。目前,我的代码运行良好,因为我正在从线程抛出异常,但我使用的是Invoke,而不是BeginInvoke 此时您可能想知道,“为什么他要创建一个线程,然后调用Invoke?为什么不直接调用一个函数?”。问题是,我想通过一个参数为调用者提供灵活性,该参数指示

这个问题已经提过很多次了,但我想再问一次,因为我在这里读到了一些对我来说似乎不正确的东西(可能是因为其中一个与.NET CF有关),我要求验证我认为合理的特定方法,并感谢您的任何反馈

无论如何,这种情况和其他人很相似——我想处理来自线程的错误。目前,我的代码运行良好,因为我正在从线程抛出异常,但我使用的是Invoke,而不是BeginInvoke

此时您可能想知道,“为什么他要创建一个线程,然后调用Invoke?为什么不直接调用一个函数?”。问题是,我想通过一个参数为调用者提供灵活性,该参数指示操作应该是同步的还是异步的

作为测试,我已经在异步操作模式下对其进行了测试,正如预期的那样,它会无声地失败,并且在从工作线程抛出异常时,应用程序会在调试器中死亡

为了确保我基本了解线程中异常的行为,以及(至少就.NET 3.5而言),我在WPF应用程序中编写了一些测试代码:

代码删除

因此,在主线程中处理来自另一个线程的事件似乎没有问题

如果您同意我上面的测试,那么我的问题很简单——在所有业务逻辑都封装在try/catch块中的情况下,编写同时提供同步和异步行为的方法是可以接受的做法吗?内部错误被困在线程内部,如果是同步调用,则抛出异常;如果是异步调用,则引发事件?在上面的示例代码中,我还在引发事件后抛出异常。我不确定这是否或为什么会给我带来任何问题

Pseudo-pseudocode:

TestFunc(async);

private TestFunc(bool async)
{
  try {
    throw new MyAppException("error occurred.");
  } catch(MyAppException ex) {
    async ? RaiseErrorEvent : throw;
  }
}
更新

好的,正如Hans所说,无论我从线程中抛出异常,它都会引起问题。我能够测试这个案例,并且确信,异常会被抛出,如果你点击F5,它会被一次又一次地抛出,并且永远不会终止线程。我不理解这种特殊的行为——它只是在运行调试器时的工作方式吗?我想这意味着我必须检查这个方法是被称为sync还是async。如果同步,则抛出错误。如果异步,则引发事件


也许更好的方法是强制客户机始终处理带有事件的错误,而不是捕获异常?有人对这种方法有想法吗?

不确定您想用这段代码证明什么。只需为AppDomain.Current.UnhandledException编写一个异常处理程序,并记录或显示e.ExceptionObject.ToString()的值

如果您正在考虑实际处理该异常,那么您将面临完全不同的局面。你有一些代码在一个随机点上运行和消亡。你不知道它进展得有多快,你的程序状态被线程改变了多少。处理异常需要恢复程序状态,撤消线程所做的任何操作。无论您编写什么事件处理程序来处理“it bombed”事件,都不可能猜到恢复状态需要做什么,因为它对线程的了解还远远不够。它只知道它不起作用。恢复状态需要由线程本身完成


处理“爆炸事件”本身就很困难。客户端代码甚至不能显示消息框,它将很容易消失在主窗口后面。不允许直接更新UI。需要将调用封送到UI线程。最好的方法是让客户机代码决定如何通知它。FileSystemWatcher.SynchronizingObject属性是一种很好的模式。

如果您谈论的是异步执行任务,最典型的模式是在线程中捕获异常,并在最终同步后重新播放,以等待任务完成。例如,有一个BeginX(),EndX()调用结构,您可以在其中调用EndX()来阻止,直到完成。EndX()调用应该抛出异步操作中发生的任何异常,以便调用方可以决定如何处理它


如果您使用的是.NET 4.0,则在执行异步任务时,对捕获甚至聚合异常提供了广泛的支持,以便启动任务的客户端可以决定如何处理这些异常。

也许我不应该发布这些代码,我只是展示了一个人为的例子,从线程中抛出异常作为一点背景信息。是的,我确实需要处理这个异常。我现在要做的是捕获线程中的异常,然后引发错误事件并抛出异常。这样,我的调用者,无论是同步还是异步,都可以随心所欲地处理错误。如果要同步调用,它将使用try/catch。如果要异步调用,它将注册/取消注册事件。我只是想征求对这种方法的意见;这似乎有效。抛出异常将轰炸程序,客户端代码无法捕获它。因为事件是在一个线程上引发的。我读到了.NET4.0的任务,对此很感兴趣。不幸的是,我要到明年初才能升级到4.0。我明白你在说什么。我不使用这种方法的原因是,我的GUI可能是sync/async方法的使用者。在GUI中,出于明显的原因,我想称之为非阻塞。如果我调用该方法,并且该方法在BeginX之后调用EndX,那么它实际上是阻塞的。这就是为什么我只叫BeginX。在这种情况下,我可以使用回调,但我只是在等待在线程退出之前引发事件。@Dave,IAsyncResult的典型使用模式是