I have a UI application which logs something every second. Every time OpenFileHandler
is fired, I must start logging to a new file. This is a very simplified version of the code:
string _logItem;
string _fileName;
CancellationTokenSource _cts;
Task _task;
private void OpenFileHandler(object sender, EventArgs e)
{
// once OpenFileHandler has been fired,
// the _logItem should go to the new file
if (_task != null && !_task.IsCompleted)
{
_cts.Cancel();
// can't do: _task.Wait();
}
if ( _fileName != null )
{
_cts = new CancellationTokenSource();
_task = LogAsync(_fileName, _cts.Token);
}
}
private async Task LogAsync(string fileName, CancellationToken ct)
{
using (var writer = new System.IO.StreamWriter(fileName, false))
{
try
{
while (true)
{
await Task.Delay(1000, ct);
await writer.WriteLineAsync(_logItem);
}
}
finally
{
writer.WriteLine("end of log!");
}
}
}
The problem: OpenFileHandler
is synchronous, but I need to make sure the pending WriteLineAsync
has completed and the old log file has been closed, before I can start a new LogAsync
task.
I cannot do _task.Wait()
inside OpenFileHandler
because it will block the UI thread.
I also cannot make OpenFileHandler
an async
method and do await _task
inside it. That's because when the application is closed, and OpenFileHandler
is fired with _fileName
being null
, I want the "end of log!"
line to still be there in the log.
How do I solve this?