Consider a piece of code like:
private Task<string> Download()
{
var wc = new WebClient();
Task<string> backgroundDownload = wc.DownloadStringTaskAsync(this.Uri);
// Make sure the WebClient is disposed no matter what.
backgroundDownload.ContinueWith((downloadTask) => { wc.Dispose(); });
return backgroundDownload;
}
Can I be certain that the WebClient.Dispose() call occurs and that any exception produced is rethrown to the caller as if there was no call to ContinueWith?
Can clients observe this ContinueWith? (e.g. will later calls to ContinueWith remove the Dispose call?)
With the code that you have you can be certain that the continuation will be fired regardless of whether or not the code completed successfully, was cancelled, or throws an exception.
The one potential problem with the solution that you have is that other continuations can potentially run, before, during, or after the web client is disposed. If you don't have a problem with other continuations running before this cleanup runs then what you have is fine. If that's a problem then you'll need to return the continuation, not the original task, but you'll also need to propagate the result (and exceptions/cancellation) correctly. The use of async makes all of this way easier:
private async Task<string> Download()
{
using(var wc = new WebClient())
return await wc.DownloadStringTaskAsync(this.Uri);
}
First of all, the continuation will be performed even if a regular exception occurred. However it is less likely to run than a regular finally block in the eventuality of exceptional conditions such as an OutOfMemoryException.
Now I would not try to dispose the webclient. Remember that disposing is an optimization, because native resources will be disposed by the finalizer anyway. The only reason we are disposing is that a finalizer is expensive because it triggers a second GC pass.
But in the order to perform your optimization the system may have to create new threads. Besides you may be prolongating the lifetime of your webclient a lot if the threadpool is filled with long running tasks.
Basically, you have to choose the lesser of two evils and I am not convinced that one less GC run is worth what you're doing. You should consider this decision in the context of your application.
Related
In my C# 7.0 Code I like to use an old school Thread of type Thread to do some work. Inside this Thread, I need to use some async methods. What would be the best approach to call these methods?
Writing the thread function async does not make any sense.
this._networkListenerThread = new Thread(/* async here is not an option */() =>
{
while (!this._listenerCancellation.IsCancellationRequested)
{
try
{
// This does not compile
var packetBuffer = await this._commProxy.ReadAsync();
doSomethingMore();
}
}
}
If we go down the call stack, finally there will be this call:
// _socket is of type Android.Bluetooth.BluetoothSocket
// .InputStream of type System.IO.Stream
// ReadAsync only returns when data arrived on the stream
// or throws an exception when the connection is lost
var receivedBytes = await this._socket.InputStream.ReadAsync(buffer, 0, buffer.Length);
For those wondering why I want to use a Thread instead of Task: I want to give it a meaningful name to enhance debugging. I did not find a way to name a Task. Besides of this, this Thread runs almost as long as the application runs, therefore a Thread does make sense for me.
this Thread runs almost as long as the application runs
No, it doesn't. Because the work that it's doing is asynchronous. The thread runs long enough to check the status of the cancellation token, fire off ReadAsync (which, being asynchronous, will return basically immediately) and then it's done. The thread goes away, and it has no more work to do. That's the whole idea of asynchronous operations; being asynchronous means the operation returns to its caller pretty much immediately, and does whatever meaningful work it has to do after returning control back to the caller (in this case, since this is the top level method of the thread, returning control back means that the thread has finished executing and gets torn down).
So there just isn't much of any purpose in creating a new thread just to have it check a boolean value and start some operation that will go off and do work on its own. It's not that you should use a different way of getting a new thread to do work (like using Task.Run), but rather you shouldn't use any means of getting a new thread to do work, because you don't have any long running CPU bound work to do. The long running (non-CPU bound, by the look of it) work that you have is already asynchronous, so you can just call the method directly from whatever thread wants to start this work, and have it do it right in line.
If you simply want to have some value that you can share along an asynchronous operation's logical call context, there are of course tools that accomplish that, such as AsyncLocal. Creating a new thread wouldn't accomplish that, because as you finish starting the asynchronous operation you have your thread is dead and gone, and the continuations will be running in some other thread anyway.
Multiple similar questions have been asked here before.
MSDN states as an important note that one should always dispose the CancellationTokenSource when done with it.
OK, but it becomes a little complicated with multithreaded applications and async-await model.
I'm developing a library. The problem I ran into is thatI'm using in several places CreateLinkedTokenSource out of a CancellationToken received from the user. Shortly, I'm doing it so that I'm able to cancel myself an operation if it takes longer than some time.
Example
public async Task<Result> DoAsync(CancellationToken cancellationToken)
{
using (var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
{
// here pass linkedTokenSource.Token further down the line
var resultTask = sender.DoAsync(linkedTokenSource.Token);
var timeoutTask = Task.Delay(timeout);
var completed = await Task.WhenAny(resultTask, timeoutTask);
if (completed == timeoutTask)
{
linkedTokenSource.Cancel();
throw TimeoutException();
}
return await resultTask;
// from the point of view of this piece of code
// we're done with the cancellationTokenSource right?
// so I need to dispose the source (done here via `using`)
}
}
However, down the line in different code sections, due to race conditions, it happens that some threads are trying to CreateLinkedTokenSource out of linkedTokenSource.Token resulting in an ObjectDisposedException since the linkedTokenSource has already been disposed after the TimeoutException was thrown.
This will end up in a UnobservedTaskException which will confuse the user if he listens on unobserved exceptions.
Putting a try-catch on every CreateLinkedTokenSource and silencing the ObjectDisposedException line seems again strange for me.
My questions are:
Why the CreateLinkedTokenSource throws this exception? Is there an explanation for this? Since the CencellationToken is a struct, why I shouldn't be able to create a new source out of it? (even in the cancellationToken is cancelled).
Any suggestions on how should handle disposing in this scenario?
This will end up in a UnobservedTaskException which will confuse the user if he listens on unobserved exceptions.
Well, sort of. UnobservedTaskException is pretty much always going to be a fact of life whenever you use Task.WhenAny (and abandon the incomplete task, which is the vast majority of the time Task.WhenAny is used).
So, they may get an ObjectDisposedException reported to UnobservedTaskException instead of an OperationCanceledException. Meh; in the async world, if you're using Task.WhenAny, you really need to ignore UnobservedTaskException anyway. Besides, a lot of "not easily cancelable" endpoints will close the underlying handle on cancellation requests, which cause (IIRC) ObjectDisposedException anyway.
Why the CreateLinkedTokenSource throws this exception? Is there an explanation for this?
It's part of those really, really old Microsoft design guidelines that were written with an '80s OOP mindset. I never agreed with MS's Dispose guidelines, preferring a much simpler model that covers all the same use cases with significantly less mental overhead.
Any suggestions on how should handle disposing in this scenario?
Just keep it as-is. UnobservedTaskException isn't a big deal.
As I can see, you've removed the rest of code with task creation. Whenether, it's very likely that your code is something like this:
public async Task<Result> DoAsync(CancellationToken cancellationToken)
{
using (var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
{
await Task.Run(() =>
{
// here pass linkedTokenSource.Token further down the line
// check if further processing reached some timeout and if it did:
if (timeout)
{
linkedTokenSource.Cancel();
throw TimeoutException();
}
// from the point of view of this piece of code
// we're done with the cancellationTokenSource right?
// so I need to dispose the source (done here via `using`)
}
}
}
So you catch a closure variable, which being used into a using construction. So it works like this:
You enter the using block
You start your task
You immediately return from the method
You execute the finally block for your method, which calls the .Dispose() method for your linkedTokenSource variable
You got a timeout
you access a disposed closure
You have to rewrite your code for manually disposing the linkedTokenSource after you are done with whole task, not when you're done with starting it.
I was writing a small console app to try to become familiar with using async/await. In this app, I accidentally created an infinite recursive loop (which I have now fixed). The behavior of this infinitely recursive loop surprised me though. Rather than throwing a StackOverflowException, it became deadlocked.
Consider the following example. If Foo() is called with runAsync set to false, it throws a StackOverflowException. But when runAsync is true, it becomes deadlocked (or at least appears to). Can anyone explain why the behavior is so different?
bool runAsync;
void Foo()
{
Task.WaitAll(Bar(),Bar());
}
async Task Bar()
{
if (runAsync)
await Task.Run(Foo).ConfigureAwait(false);
else
Foo();
}
It's not really deadlocked. This quickly exhausts the available threads in the thread-pool. Then, one new thread is injected every 500ms. You can observe that when you put some Console.WriteLine logging in there.
Basically, this code is invalid because it overwhelms the thread-pool. Nothing in this spirit may be put into production.
If you make all waiting async instead of using Task.WaitAll you turn the apparent deadlock into a runaway memory leak instead. This might be an interesting experiment for you.
The async version doesn't deadlock (as usr explained) but it doesn't throw a StackOverflowException because it doesn't rely on the stack.
The stack is a memory area reserved for a thread (unlike the heap which is shared among all the threads).
When you call an async method it runs synchronously (i.e. using the same thread and stack) until it reaches an await on an uncompleted task. At that point the rest of the method is scheduled as a continuation and the thread is released (together with its stack).
So when you use Task.Run you are offloading Foo to another ThreadPool thread with a clean stack, so you'll never get a StackOverflowException.
You may however, reach an OutOfMemoryException because the async method's state-machine is stored in the heap, available for all threads to resume on. This example will throw very quickly because you don't exhaust the ThreadPool:
static void Main()
{
Foo().Wait();
}
static async Task Foo()
{
await Task.Yield();
await Foo();
}
I'm trying to use HttpResponse BeginFlush and EndFlush methods in order to make the flush async, which means my worker thread won't being used while flushing to the stream.
However it seems that the BeginFlush methods run in synchronous way always.
I dig in Microsoft reference code and didn't find the reason for this behavior.
This is Microsoft implementation: http://referencesource.microsoft.com/#System.Web/HttpResponse.cs,f121c649c992c407
I checked the SupportsAsyncFlush flag and I'm getting true , so my environment actually supports the AsyncFlush.
Any idea?
This is a code snippet for trying to do the async flush, but I'm not getting to the "Different Threads" line - it is always the same thread that runs this code.
Context.Response.Write("Some message");
Context.Response.BeginFlush(
res =>
{
try
{
var previousThreadId = (int)res.AsyncState;
var thread2Id = Thread.CurrentThread.ManagedThreadId;
if (previousThreadId != thread2Id)
{
Console.WriteLine("Different Threads");
}
Context.Response.EndFlush(res);
}
catch (Exception e)
{
}
},
Thread.CurrentThread.ManagedThreadId);
The code is asynchronous, but it's not multithreaded. You're defining a callback; a method that will be run at some indeterminate point in the future when the flush finishes. That doesn't necessarily mean that it'll run on another thread.
There are also many implementations of abstract functionality in .NET where the behavior is defined as asynchronous, but the implementation is synchronous because that particular implementation expects to run so quickly as to not warrant asynchrony. This is true for a fair bit of .NET's file IO. If the writer you're using expects to be able to flush the buffer very quickly, it may not bother doing it asynchronously.
The effect you are seeing may be related to SycnhronizationContext used by ASP.NET. Depending on .NET version and whether your code executes under ASP.NET page or something else, the behavior may change. Generally, it is normal for the SynchronizationContext to execute the callback on the same thread which started the async operation. You can find more info here: https://msdn.microsoft.com/en-us/magazine/gg598924.aspx
In any case, you can check whether the callback is synchronous or not by checking weather the next line of your code (after BeginFlush) executes before the callback. That will indicate that the callback is indeed asynchronous.
I had thought this was a reasonable pattern to use to call WebClient DownloadData asynchronously in an event handler:
private async void button1_Click(object sender, EventArgs e)
{
WebClient wc = new WebClient();
//wc.Proxy = null;
byte[] bytes = await wc.DownloadDataTaskAsync("http://www.google.com");
label1.Text = Encoding.ASCII.GetString(bytes);
}
But I find DownloadDataTaskAsync blocks for about 5 seconds before returning (unless the wc.Proxy = null statement is uncommented). What's the point of a method being awaitable if it can at a whim perform non-trivial work before even returning the task?
Presumably this means to be safe I should never call xAsync methods as above but instead should always wrap them in a Task.Run() myself to be sure. Or not?
This is a known issue with WebClient/HttpWebRequest: the proxies and DNS lookups are always done synchronously. This is a bug, but Microsoft has pretty much decided not to fix it for backwards compatibility reasons.
The first thing I'd recommend is to use HttpClient. If that doesn't work and you need asynchrony, then you can wrap the call in Task.Run.
It turns out that WebClient.DownloadDataTaskAsync is calling HttpWebRequest.BeginGetResponse
MSDN points out:
The BeginGetResponse method requires some synchronous setup tasks to
complete (DNS resolution, proxy detection, and TCP socket connection,
for example) before this method becomes asynchronous. As a result,
this method should never be called on a user interface (UI) thread
because it might take considerable time (up to several minutes
depending on network settings) to complete the initial synchronous
setup tasks before an exception for an error is thrown or the method
succeeds.
http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetresponse(v=vs.110).aspx
Unfortunately the MSDN documentation for WebClient.DownloadDataTaskAsync says:
This operation will not block.
which seems to not be strictly true.