우선, 제 문제를 자세히 설명하는 것은 어렵지만 최선을 다할 것입니다. 나는 아마 예외를 야기한 나에 의해 사용 된 상세한 설명이나 더 많은 코드로 업데이트 할 것이다. 코드가 엉망이라면 유감입니다."작업의 예외가 관찰되지 않았습니다 ..."원인을 찾으십시오.
내가 읽은 동일한 제목의 많은 SO 질문이 있지만 운이별로 없습니다. Thread/Task/Dispatcher에 대한 이해가 거의 없으므로, 제 코드에 대해 잘못된 점을 발견하면 안내해주십시오.
Intoduction
내 응용 프로그램 타이머에 의해 모든 N분를 백그라운드 작업을 수행합니다.
백그라운드 작업 : API에서 데이터를 가져온 다음 데이터를 포함 할 양식으로 Window 요소를 생성 한 다음 인쇄합니다.
문제 : : 예외가 이미 두 번 발생하여 인쇄되지 않도록 두 개의 양식 문서가 생성되지 않습니다. TaskScheduler.UnobservedTaskException
에서 얻을 수있다
자세한 예외입니다 :
-
작업의 예외 (들)이 관찰되지 않았다 중 작업에 대기 또는 예외 속성에 액세스하여. 결과적으로 관찰되지 않는 예외는 finalizer 스레드에 의해 다시 발생되었습니다.
: 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
);
}
... :
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
은 다음과 ShippingLabelForm
InvoiceForm
는 await Task.Delay(delay)
포함 모두에서
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
.
내가 작성한 코드에서 실수가 있습니까? Dispatcher.Invoke
의 잘못된 사용으로 인해 발생 했습니까? 열거 형의 잘못된 사용으로 인해 발생합니까? Task.Delay
작동에 문제가 있습니까?
invoiceForm.CreateDocument (invoiceTmp)에 의해 발생한 모든 예외를 catch하면 어떨까요? – mm8
@ mm8 나는 모든 처리되지 않은 예외를 이미 잡았습니다. 제가 언급 한 것은 잡힌 유일한 것입니다. –
invoiceForm.CreateDocument (invoiceTmp)를 기다리는 호출에는 catch 절이 없습니다. – mm8