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

在任务c#中不等待地重新触发异常

在任务c#中不等待地重新触发异常,c#,exception,task,C#,Exception,Task,我有一个GUI应用程序,我想在其中运行任务中的某些内容,因此它不会保存UI。我希望将任务中未处理的异常传播到应用程序级异常处理程序。 然而: 如果我只是在任务中抛出一个异常,它将不会达到应用程序级别 除非我使用wait/await,否则会出现异常 Async/Await—我从UI构造函数调用该方法,因此不能在那里使用Async/Await,因为我需要继续构造。我只想执行任务,然后忘记 我在考虑使用dispatcher.invoke,你觉得怎么样 public MainWindow() {

我有一个GUI应用程序,我想在其中运行任务中的某些内容,因此它不会保存UI。我希望将任务中未处理的异常传播到应用程序级异常处理程序。 然而:

  • 如果我只是在任务中抛出一个异常,它将不会达到应用程序级别 除非我使用wait/await,否则会出现异常
  • Async/Await—我从UI构造函数调用该方法,因此不能在那里使用Async/Await,因为我需要继续构造。我只想执行任务,然后忘记 我在考虑使用dispatcher.invoke,你觉得怎么样

    public MainWindow()
    {
            InitializeComponent();
    
            MyMethodAsync();
    
            InitializeA();
            IntiializeB();
    }
    
    private void MyMethodAsync()
    {
         Task t = Task.Run(() =>
         {
              //Do some stuff
              throw new Exception("Throwing some unexpected exception");
         }).ContinueWith(MyContinueWith);
    }
    
    private void MyContinueWith(Task task)
    {
        if (task.IsFaulted && task.Exception != null)
        {
             dispatcher.BeginInvoke(new Action(() =>
             {
                throw task.Exception;
             }), null);
        }
    }
    

    我可以想到两种方法。首先,是注册事件并记录您需要的内容:

    private void MyMethodAsync()
    {
        // Note you should probably register only once, so this may not fit here.
        TaskScheduler.UnobservedTaskException += (s, e) => GlobalLogger.Log(e);
        Task t = Task.Run(() =>
        {
            // Do some staff
        }).ContinueWith(MyContinueWith);
    }
    
    出于某些原因,您不想使用的更好的选择是实际等待操作并将其包装在一个
    try catch

    private async Task MyMethodAsync()
    {
        try
        {
           await Task.Run(() =>
           {
              // Do some staff
           });
           InvokeContinuation();
        }
        catch (Exception e)
        {
            // Log.
        }
    }
    

    请务必意识到,通过调用Task.Run,您通常会生成一个新线程,而这在大多数情况下不太可能是您想要的。在一些正在进行CPU绑定工作的实例中创建新线程是有意义的,在这些情况下,您将考虑考虑利用其他来获得最大化。相反,如果您的工作受I/O限制,您应该能够一直使用异步调用


    为了等待异步方法调用的结果或异常冒泡到调用点,您可以始终附加一个调用,以继续执行异步方法返回的任务。如果您同时处理结果和任何可能的异常,那么异步/等待语义工作得很好。但是请注意,默认情况下,在这些延续中执行的代码可能不会在与原始线程相同的线程中执行。

    按照惯例,后缀为“Async”的方法通常是返回已启动任务的方法。使用async/await关键字,调用方会自动处理这一问题,其实实现并不重要。@skippy:
    await
    不会阻塞您的UI。听起来
    wait
    正是您想要的行为。为什么要使用
    任务。是否继续使用
    ?确实不推荐使用,您应该使用C#5
    wait
    。单是调试的潜力就使得使用
    任务变得疯狂。继续使用
    。感谢您的快速回答。我不想使用wait的原因是我想在UI线程上运行的构造函数中使用MyMethodAsync。因此,我不想等待和举行我的窗口建设。(我无法将构造函数设置为异步)我已使用此commentHi Yuval编辑了该问题,正如我之前评论的那样,我与-await的问题是,我希望在UI构造函数中使用MyMethodAsync,而我不希望使用await保留构造函数操作,我只想跑然后忘记。@skippy然后选择第一个选项。我已经选中了第一个选项,但它似乎没有帮助。只有当任务由GC收集时,它才会转到事件(我不知道它何时发生,除非调用GC.Collect,否则它不会到达我的示例中的处理程序)。我现在注意到,当它是GC时,异常将被抛出,并到达我的应用程序级异常处理程序,这很好,但我仍然希望在异常发生时到达那里,而不是依赖于某个时间GC@skippy然后您需要同步或异步等待。同步-我不能,因为它将保存我的UI,异步地。。。?我如何做到这一点(不回到同样的问题上)