2017-03-07 59 views
0

首先,让我说,这是很难详细解释我的问题,但我会尽我所能。我会用更详细的解释或更多的代码来更新,这些代码可能会导致异常。如果我的代码很混乱,我很抱歉。寻找是什么导致“没有发现任务的例外......”

有很多SO问题与我已阅读的相同标题,但我没有运气。我在这里对Thread/Task/Dispatcher有一点点的理解,所以如果你发现我的代码有问题,请指导我。


Intoduction

我的应用程序通过定时器做后台任务每ñ分钟。

后台任务:从API获取数据,然后生成窗口元件,以包含所述数据的形式,然后打印它们。

问题:此时异常已发生两次,这会阻止生成两个表单文档,因此它们不会被打印。

的详细的异常是从TaskScheduler.UnobservedTaskException得到的是:

  • 任务的异常(或多个)未观察到无论是等待在Task或访问其Exception属性。结果,未被观察到的异常被终结器线程重新抛出。

  • 堆栈跟踪:N/A
  • 内部异常:

    System.Collections.ObjectModel.ReadOnlyCollection`1 [System.Exception的]


这里是我的一段代码,可能对您有用,可以找到问题的根源:

public void BackgroundTask(object sender, EventArgs e) 
{ 
    Application.Current.Dispatcher.Invoke(
     new Action(GetInvoiceData), 
     DispatcherPriority.Background, 
     null 
    ); 
} 

...其中GetInvoiceData是:

public async void GetInvoiceData() 
{ 
    try 
    { 
     JsonData = await ApiHelperInstance.Post(ApiParam); 
    } 
    catch (Exception ex) 
    { 
     Console.WriteLine(ex.Message); 
    } 
    finally 
    { 
     if (!string.IsNullOrEmpty(JsonData)) 
     { 
      var apiReturn = new ApiReturn(); 

      try 
      { 
       apiReturn = JsonConvert.DeserializeObject<ApiReturn>(JsonData); 
      } 
      catch (JsonException ex) 
      { 
       Console.WriteLine(ex.Message); 
      } 
      finally 
      { 
       if (apiReturn.Result != null) 
       { 
        foreach (ApiResult apiResult in apiReturn.Result) 
        { 
         InvoiceQueue.Enqueue(new Invoice(apiResult)); 
        } 

        var worker = new BackgroundWorker(); 
        worker.DoWork += GenerateDocumentAndPrint; 
        worker.RunWorkerAsync(); 
       } 
      } 
     } 
    } 
} 

...和GenerateDocumentAndPrint是:

public void GenerateDocumentAndPrint(object sender, DoWorkEventArgs e) 
{ 
    while (InvoiceQueue.Count != 0) 
    { 
     Dispatcher.Invoke(() => 
     { 
      Invoice invoice = InvoiceQueue.Dequeue(); 

      var invoiceForm = new InvoiceForm(); 
      var shippingLabelForm = new ShippingLabelForm(); 

      invoiceForm.Dispatcher.Invoke(async() => 
      { 
       var invoiceTmp = invoice; 
       var invoiceDoc = new FixedDocument(); 

       try 
       { 
        invoiceDoc = await invoiceForm.CreateDocument(invoiceTmp); 
       } 
       finally 
       { 
        InvoiceDocumentName = PrintJobNameSub + " - Invoice #" + invoice.TransOrder.TransNumber; 
        PrintHelperInstance.SetPrinterByName(InvoicePrinterName); 
        PrintHelperInstance.PrintDocument(invoiceDoc.DocumentPaginator, InvoiceDocumentName); 
        invoiceForm.Close(); 
       } 
      }, DispatcherPriority.ContextIdle); 

      shippingLabelForm.Dispatcher.Invoke(async() => 
      { 
       var invoiceTmp = invoice; 
       var shippingLabelDoc = new FixedDocument(); 

       try 
       { 
        shippingLabelDoc = await shippingLabelForm.CreateDocument(invoiceTmp); 
       } 
       finally 
       { 
        ShippingLabelDocumentName = PrintJobNameSub + " - Shipping Label #" + invoice.TransOrder.TransNumber; 
        PrintHelperInstance.SetPrinterByName(ShippingLabelPrinterName); 
        PrintHelperInstance.PrintDocument(shippingLabelDoc.DocumentPaginator, ShippingLabelDocumentName); 
        shippingLabelForm.Close(); 
       } 
      }, DispatcherPriority.ContextIdle); 
     }, DispatcherPriority.Normal); 
    } 
} 

...和异步方法CreateDocument从两个InvoiceFormShippingLabelForm包含await Task.Delay(delay)


有我从我的代码所做的任何错误?是否由于错误地使用了Dispatcher.Invoke而引起?是否因使用DispatcherPriority enum错误引起? Task.Delay操作有问题吗?

+0

如果发现由invoiceForm.CreateDocument(invoiceTmp)引发的任何异常,该怎么办? – mm8

+0

@ mm8我已经捕捉到了所有未处理的异常,我刚才提到的异常是唯一被捕获的异常。 –

+0

您在调用等待invoiceForm.CreateDocument(invoiceTmp)时没有catch子句。 – mm8

回答

1

TaskScheduler.UnobservedTaskException在未观察到任务异常时会收到异常。如果你所有的任务都是await,那么这个事件永远不会开火。

请注意,该事件并不一定意味着严格意义上的错误。例如,如果您放弃任务,则可能发生这种情况 - 如果您的代码包含任何Task.WhenAny调用,则这很常见。这也可能发生,如果一个“失火和遗忘”任务引发异常。在这两种情况下,它实际上并不是错误。在WhenAny的情况下,不同的任务已经完成了Task.WhenAny,所以你不关心另一个任务是否抛出异常。在“忘却遗忘”的情况下,“遗忘”的字面意思是“我不在乎异常”,所以你不应该在乎它是否抛出异常。

此事件仅指示错误如果您不小心遗漏了await。找到丢失的await最简单的方法是检查内部例外的调用堆栈,然后检查该方法的调用者等,直到找到不正确的任务。

相关问题