gpt4 book ai didi

c# - 寻找导致未观察到 "A Task' 异常的原因...”

转载 作者:行者123 更新时间:2023-12-02 00:47:32 24 4
gpt4 key购买 nike

首先,让我说一下,很难详细解释我的问题,但我会尽力而为。我将更新详细的解释或我使用的可能导致异常的更多代码。如果我的代码困惑,我很抱歉。

我读过很多同标题的SO问题,但我一点运气都没有。我在这里对Thread/Task/Dispatcher了解甚少,如果您发现我的代码有问题,请指导我。


简介

我的应用程序每 n 分钟通过计时器执行一次后台任务。

后台任务:从 API 获取数据,然后生成 Window 元素作为包含数据的表单,然后打印它们。

问题:此时已经出现两次异常,导致生成两个表单文档无法打印。

TaskScheduler.UnobservedTaskException获取的详细异常是:

  • A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread.

  • 堆栈跟踪:不适用
  • 内部异常:

    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);
}
}

...InvoiceFormShippingLabelForm 中的异步方法 CreateDocument 包含 await Task.Delay(delay).


我的代码有什么错误吗?是不是错误使用了Dispatcher.Invoke造成的?是不是 DispatcherPriority enum 的错误使用造成的? Task.Delay操作有问题吗?

最佳答案

TaskScheduler.UnobservedTaskException 在未观察到任务异常时获取异常。如果您await 所有任务,则永远不会触发此事件。

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

如果您不小心错过了 await,此事件只会指示一个错误。找到丢失的 await 的最简单方法是检查内部异常的调用堆栈,然后检查该方法的调用者等,直到找到不正确的 await 正在执行任务。

关于c# - 寻找导致未观察到 "A Task' 异常的原因...”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42647511/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com