I searched online but there is very little information regarding ThreadHelper.JoinableTaskFactory.RunAsync
If I have the following code, Test1
runs on MainThread
:
public bool Test1()
{
// Do something here
ThreadHelper.JoinableTaskFactory.RunAsync(this.Test2);
// Do something else
return false;
}
private async Task Test2()
{
await TaskScheduler.Default;
// do something here
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
// do something here
}
Is it ok if the RunAsync
has never been awaited on? What would happen if Test1
returns before Test2
finishes running?
Is it ok if the RunAsync has never been awaited on?
That depends. It's OK from JoinableTaskFactory
's perspective. All the necessary continuations will continue -- it's just that your calling method won't wait for it to complete, which is the whole point of not awaiting it if you choose to do so.
But in general, it may not be healthy for your app. Consider the case that your async work is saving a file (or transmitting something over the network) and the user closes your app. Wouldn't you want the app to wait for it to finish before closing? As @GrzegorzSmulko said in his answer, the JoinableTaskFactory
prescribes a pattern for blocking on shutdown (or disposal of your object) to ensure async work completes.
There's another reason to track your async work if you're in an app that hosts the CLR and shuts it down before exiting: you don't want managed threads running around doing arbitrary things when the AppDomain is being finalized or you'll find that your app crashes on shutdown. This is not a concern when you have a pure-managed app though, since it just exits without shutting down the CLR. It will not crash, but it will still abandon any half-done work.
All the foregoing is true in any app that you use JoinableTaskFactory
for. If you happen to be using it within Visual Studio (I'm speaking generally here for a broader audience... I know your question specifically mentioned VS) then the rules are stressed more. You should track all your async work as prescribed in that section. You shouldn't have any "fire and forget" work.
The FileAndForget
extension method is actually intended for internal Microsoft use since it sends errors to our telemetry servers. If you really want to just forget stuff, you can use the .Forget()
extension method. But remember you should only use that after scheduling the work using an AsyncPackage.JoinableTaskFactory
instance or another one that is tracking your async work for disposal. Don't use it on ThreadHelper.JoinableTaskFactory
because that doesn't track async-and-forgotten work. So for example, don't do this:
ThreadHelper.JoinableTaskFactory.RunAsync(async () => { /* something async */ }).Forget();
The problem with the above is that the async work will not be tracked, and thus not block shutdown. You should do this instead:
myAsyncPackage.JoinableTaskFactory.RunAsync(async () => { /* something async */ }).Forget();
Or even better: just await the call, in which case you can use pretty much any JTF instance:
await ThreadHelper.JoinableTaskFactory.RunAsync(async () => { /* something async */ });
But if you're in a context where you can use await, you often don't need JoinableTaskFactory.RunAsync
at all, since if you can just await the code within the delegate itself. Some uncommon scenarios may require that you still track the async work with a JoinableTaskCollection
where you might want to use await someJtf.RunAsync
but normally you can just drop JTF use where you can naturally await your work.
According to Threading Cookbook for Visual Studio you should use ThreadHelper.JoinableTaskFactory.RunAsync()
together with FileAndForget()
.
The potential problem is, that FileAndForget()
is not available in VS2015, but only in VS2017+.
Is it ok if the
RunAsync
has never been awaited on?
I think it's not ok, you should use FileAndForget
. But, I don't really know what to do for VS2015.
What would happen if
Test1
returns beforeTest2
finishes running?
This should be pretty easy to test to make sure. I assume that Test2
will just finish later "But you also should be sure your async work finishes before your object claims to be disposed."
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With