I have a method RenderReport
which generates a PDF file (byte[]
). This can sometimes hang indefinitely. It should take no more than 15 seconds to complete when successful. Hence, I'm using a TaskCompletionSource
to be able to limit the execution time and throw a TimeoutException
if it exceeds the timeout.
However, what I can't determine is: how do you provide the byte[]
file returned by RenderReport
to the SetResult
in the following code? longRunningTask.Wait
returns a boolean and not the file so where do you get the file from?
I don't want to use longRunningTask.Result
as that can introduce deadlock issues. Here's my code:
public async Task RunLongRunningTaskAsync()
{
Task<byte[]> longRunningTask = Task.Run(() => RenderReport());
TaskCompletionSource<byte[]> tcs = new TaskCompletionSource<byte[]>();
Task toBeAwaited = tcs.Task;
new Thread(() => ThreadBody(longRunningTask, tcs, 15)).Start();
await toBeAwaited;
}
private void ThreadBody(Task<byte[]> longRunningTask, TaskCompletionSource<byte[]> tcs, int seconds)
{
bool completed = longRunningTask.Wait(TimeSpan.FromSeconds(seconds));
if (completed)
// The result is a placeholder. How do you get the return value of the RenderReport()?
tcs.SetResult(new byte[100]);
else
tcs.SetException(new TimeoutException("error!"));
}
private byte[] RenderReport()
{
using (var report = new Microsoft.Reporting.WinForms.LocalReport())
{
// Other logic here...
var file = report.Render("PDF", null, out _, out _, out _, out _, out var warnings);
if (warnings.Any())
{
// Log warnings...
}
return file; // How do I get this file?
}
}