Open szmcdull opened 3 years ago
I want to find out which tasks are out running.
Unfortunately, AsyncEx can't help you with that, since it doesn't have that information.
the _outstandingOperations is not matching with _queue.Count
The _outstandingOperations
tracks the number of "operations" that have been registered with the SynchronizationContext
. Depending on how you use AsyncContext
, it may use 0 or 1 internally, and the rest represent async void
methods. The _queue
is the continuations that have been queued to the AsyncContext
. These track different kinds of asynchronous operations and aren't supposed to be the same.
If the screenshot you posted is at a time when you expected the AsyncContext
to be complete, then you can conclude that since _outstandingOperations
is 3
, then there are at least two async void
methods that have not completed.
By async void
do you mean async void Func(...)
? I see _outstandingOperations is increased from AsyncContext.TaskScheduler.Enqueue(Task)
. These Tasks are mainly completion callbacks from other threads than the main thread, for example, timer or socket callbacks.
private void Enqueue(Task task, bool propagateExceptions)
{
OperationStarted();
task.ContinueWith(_ => OperationCompleted(), CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, _taskScheduler);
_queue.TryAdd(task, propagateExceptions);
tSynchronizationContext(WinFormsSynchronizationContext).
}
private void OperationCompleted()
{
var newCount = Interlocked.Decrement(ref _outstandingOperations);
if (newCount == 0)
_queue.CompleteAdding();
}
public void Execute()
{
SynchronizationContextSwitcher.ApplyContext(_synchronizationContext, () =>
{
var tasks = _queue.GetConsumingEnumerable();
foreach (var task in tasks)
{
_taskScheduler.DoTryExecuteTask(task.Item1);
// Propagate exception if necessary.
if (task.Item2)
task.Item1.WaitAndUnwrapException();
}
});
}
This is where _outstandingOperations is mainly increased and decreased (the other 2 is in AsyncContext.Run
). Seems _outstandingOperations is highly bound with _queue. Each time _outstandingOperations is increased a task will be added to the queue. The task will be then popped from the queue and executed. When it is complete, the counter decreases.
OK I found out that AsyncVoidMethodBuilder does call SynchronizationContext.OperationStarted.
Anyway, I decide to forcefully decrease _outstandingOperations when I believe my program should exit, using reflection haha
Ah, I forgot that it's also used in Enqueue
.
I decide to forcefully decrease _outstandingOperations when I believe my program should exit, using reflection
I strongly recommend against this. I recommend finding what code isn't completing and ensure it completes, instead.
I understand that AsyncContext would not stop until all tasks are finished. I want to find out which tasks are out running. But I didn't find out a good way. Both the Tasks view and Parallel Stacks view didn't help. Then I found something strange, the _outstandingOperations is not matching with _queue.Count I read the source but didn't find any clue. Can you help me?