Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/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#异步lambda世界中的错误处理策略?_C#_Silverlight_Asynchronous - Fatal编程技术网

c#异步lambda世界中的错误处理策略?

c#异步lambda世界中的错误处理策略?,c#,silverlight,asynchronous,C#,Silverlight,Asynchronous,我过去常常编写厚厚的c#客户机代码,将异常抛出引擎室(比如说网络故障),并期望我之上的人来处理它。最终会出现一个appwide的try/catch来处理剩余内容(“foo bar中的意外异常,单击了解详细信息,联系支持人员…”),另外可能还会出现一个appdomain范围的未处理异常处理程序以防万一 现在我正在用Silverlight编写一个“厚”客户机,我不知道该怎么做了。我的大量引擎室代码作为网络事件驱动回调运行,然后我调用原始调用方提供给我的lambda;但它们早已消失。我不能向他们抛出一

我过去常常编写厚厚的c#客户机代码,将异常抛出引擎室(比如说网络故障),并期望我之上的人来处理它。最终会出现一个appwide的try/catch来处理剩余内容(“foo bar中的意外异常,单击了解详细信息,联系支持人员…”),另外可能还会出现一个appdomain范围的未处理异常处理程序以防万一

现在我正在用Silverlight编写一个“厚”客户机,我不知道该怎么做了。我的大量引擎室代码作为网络事件驱动回调运行,然后我调用原始调用方提供给我的lambda;但它们早已消失。我不能向他们抛出一个例外,没有一堆东西可以冒出来。我不能强迫他们放松。它们仍然处于挂起状态(无论这对特定异步调用意味着什么)

我看到AsyncEventCompletedArgs及其RaiseExceptionIfNeeded技巧。使用它似乎将我的低级管道暴露给了更高级的代码(想想MVVM、MVC等等)。我希望帮助上层代码在默认情况下“做正确的事情”,就像他们在旧的同步/异常驱动时代所做的那样。但这没有帮助。它们从AsyncArgs实例读取结果,该实例抛出,回调终止,使它们在逻辑上仍然悬空

无论如何,希望这是有意义的。是否有人有任何设计,经验,他们想分享。任何SL MVVM、MVC框架都做什么

注意——我不是在谈论c#5中的新奇的异步功能(这会有帮助吗?)


(可能会因为不够具体、太主观等等而关闭)

我使用以下结构的代码异步处理异常问题:

        void ClientAsyncOperationCompleted(object sender, AsyncOperationEventArgs e)
        {
            if (e.Error == null) {
                //Normal execution path
            }
            else {
                //you can put your structured exception handling code here around e.Error
                if(e.Error is ConcreteException) {
                   //concrete exception handling
                }
                else {
                   //general exception handling
                } 
            }
        }
如果方法是异步执行的,则无法获得同步异常抛出,除非我们包装异步方法并使用一些线程同步构造(例如
ManualResetEvent
)同步其执行。所以,如果我们接受异步处理异常,在AsyncCompleted内部,您可以调用所需的Oops(异常e)方法,如下所示:

void ClientAsyncOperationCompleted(object sender, AsyncOperationEventArgs e)
{
    if (e.Error == null) {
       //Normal execution path
    }
    else {
       Oops(e.Error);
    }
}
DoAsync(
  () => BackgroundThreadWork(), // executed on background thread
  result => {                   // executed on UI thread
    if(result.Error != null)
      throw result.Error;
    HandleResultOnUIThread(result.Value);
  });

这是没有Rx的情况,Rx非常复杂,但功能强大。

您可以让调用方提供lambda以成功完成,也可以让lambda在代码中捕获异常的情况下接受异常

反应式扩展在订阅可观察对象时允许这样做

大致如下:

asyncCall.Subscribe(result => DoSomething(result), ex => Oops(ex));

诀窍是将异常返回到UI线程。你仍然想呕吐,直到有人像以前一样处理它,但是你必须在线程的顶层捕获它,并将它传递回主线程,然后像往常一样在那里处理它。有两种方法可以做到这一点,Silverlight中最简单的方法是使用BackgroundWorker,但最简单的方法是基本上为所有返回值或错误的异步方法提供回调。大概是这样的:

void ClientAsyncOperationCompleted(object sender, AsyncOperationEventArgs e)
{
    if (e.Error == null) {
       //Normal execution path
    }
    else {
       Oops(e.Error);
    }
}
DoAsync(
  () => BackgroundThreadWork(), // executed on background thread
  result => {                   // executed on UI thread
    if(result.Error != null)
      throw result.Error;
    HandleResultOnUIThread(result.Value);
  });
下面是一个非常简单的异步操作队列的示例,它可能很容易转换为Silverlight友好的版本:


我使用队列是因为它允许我保证在后台线程上完成的工作顺序。当您有一堆异步操作时,很容易进入竞争条件,因此,队列是一种很好的结构,可以保证它们的执行顺序,即使它们实际上都是异步的。queueGroup适用于您也希望并行和异步的操作。

如果您的需求包括重要的并行、未完成的异步操作,那么就不用再阅读这个答案了。但是,如果操作是按顺序调用的(一个操作直到另一个操作完成后才调用),听起来可能是这样的,那么您可能会发现这里提到的内容有些有用

在Silverlight中处理异步代码是我感兴趣的主题。我已经写了几篇博客,介绍了我称之为
asynchhoperationservice
的东西,它支持使用简单的同步顺序样式编写代码,并提供了对错误处理的良好支持

从中挑选出来

Rx可能是一个选项,它看起来确实很强大。尽管它很复杂,但它最初设计用于处理传入事件流。我不相信(尽管我承认我的研究还很肤浅)这是一个“开始做某事,稍后再回应”操作的好方法

就我个人而言,我喜欢事情简单明了,但很明显,我需要完全改变我的编码方式,以适当地包含Rx的功能,我相当确定生成的代码不会那么容易阅读

而使用
AsyncOperationService
时,它的底纹很轻,一旦我创建了一些有用的单行函数,生成的代码序列就非常直观了


有什么问题吗?嗯,有一个,它要么正是你所需要的,要么正是你所需要的。该方法基于一系列异步操作需要按顺序完成的假设。如果您的需求是重要的并行操作,那么当前形式的
AsyncOperationService
不适合您(尽管这可能会改变)。

我不得不说,收益率回报的使用非常聪明。我从来没有想到过它,我想他指的是“Rx”的反应式扩展,这就是我要说的。我担心的是,在我的上层“纯语义”层中,我暴露了太多的管道细节,我不认为“成功时执行此操作”和“失败时执行此操作”是管道细节。。。如果你能在正确的位置抛出异常,那么不管怎么说,它都会被放在捕获块中。我看了巴特在RX上的演示。让我觉得我太胆小了:我真的需要完全颠倒我的申请,