First of all, let me say that, it's so hard to explain my problem in detail, but I will try my best. I will update with a detailed explanation or more codes which is used by me that probably caused the exception. And I'm sorry if my code is messy.
There are many SO questions with the same title that I have read, but I have no luck at all. I have a very little understanding of Thread/Task/Dispatcher here, so please guide me if you find something wrong about my code.
Intoduction
My application does the background task by timer every n minutes.
The background task: fetches data from API, then generates Window element as a form to contain the data, then prints them.
The problem: The exception has already occured twice at the moment, which prevents two form documents to be generated so they are not printed.
The detailed exception which is get from TaskScheduler.UnobservedTaskException
is:
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.
- Stack Trace: N/A
- Inner Exception:
System.Collections.ObjectModel.ReadOnlyCollection`1[System.Exception]
Here is my piece of code that may be useful for you to find the source of the problem:
public void BackgroundTask(object sender, EventArgs e)
{
Application.Current.Dispatcher.Invoke(
new Action(GetInvoiceData),
DispatcherPriority.Background,
null
);
}
...where GetInvoiceData
is:
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();
}
}
}
}
}
...and GenerateDocumentAndPrint
is:
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);
}
}
...and async method CreateDocument
from both of InvoiceForm
and ShippingLabelForm
contains await Task.Delay(delay)
.
Is there any mistake I made from my code? Is it caused by wrong use of Dispatcher.Invoke
? Is it caused by wrong use of DispatcherPriority
enum? Is it something wrong with the Task.Delay
operation?