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?