I have the following bit of code the calls out to two different command line components (each wrapped in their own Task)
public async Task<FileInfo> RasterizeAllPdfs(IEnumerable<Uri> targetUris, FileInfo destination = null)
{
// rasterize uris to files in the rasterizedOutput directory
await rasterize(rasterizedOutput.Value, targetUris);
// concatenate all pdfs in this directory
return await concatenatePdfs(rasterizedOutput.Value.EnumerateFiles("*.pdf"), destination);
}
What I would like is for the method to return a task immediately and for the returned task to become resolved once the task returned by concatentatePdfs finishes running.
It seems to work correctly (as in it's returning correct output) but I'm not 100% sure that I'm using the async and await keywords properly
1 Answer 1
You are using async
/await
absolutely correctly, that's how they were supposed to be used.
Please note that from this code it's hard to tell whether the method will return the Task
immediately, since it will be waiting synchronously for rasterize
method to return the Task
, and thus the answer depends on the implementation of rasterize
.
As a side note - you are using implicit dependency here (first method prepares files in folder, and second method enumerates all pdf files there). I would prefer explicit dependency: rasterize
to return a collection of FileInfo objects consumed by the concatenatePdfs
method.
-
\$\begingroup\$ Thanks, this is all private to a class so I'm not terribly concerned about explicit vs implicit dependencies. I think I might want to change what I'm doing though. I want the second method to be a continuation of the first completing successfully but I don't want to block the thread while this happens (hence return immediately). Do I have to use
ContinueWith()
in that case? Is that correct? Basically if this was jQuery deferreds I would want to returnfirstMethodDeferred.pipe(secondMethod)
. \$\endgroup\$George Mauer– George Mauer2013年01月30日 22:02:02 +00:00Commented Jan 30, 2013 at 22:02 -
\$\begingroup\$
await
does exactly that. You can think of it as "the code after await will execute after the awaiting task completes". It's implemented slightly differently toContinueWith
, but idea is the same \$\endgroup\$almaz– almaz2013年01月30日 22:15:44 +00:00Commented Jan 30, 2013 at 22:15 -
\$\begingroup\$ So I'm not quite clear how to combine the two, simply placing the second line into a
ContinueWith
block doesn't work because now my return isTask<Task<FileInfo>>
I basically have two tasks that I want to combine to run in sequence \$\endgroup\$George Mauer– George Mauer2013年01月30日 22:27:57 +00:00Commented Jan 30, 2013 at 22:27 -
\$\begingroup\$ And about "I don't want to block the thread while this happens" - it will not block the thread if
rasterize
doesn't do heavy things synchronously, that is before the first await (assuming you're using awaits there as well). Just for you to understand: the first part of the method till firstawait
is executed synchronously, and will continue to run synchronously in case when task being awaited is already completed at the time of awaiting. \$\endgroup\$almaz– almaz2013年01月30日 22:28:10 +00:00Commented Jan 30, 2013 at 22:28 -
\$\begingroup\$ "So I'm not quite clear..." - you don't need
ContinueWith
here, your current code will run methods in sequence \$\endgroup\$almaz– almaz2013年01月30日 22:30:33 +00:00Commented Jan 30, 2013 at 22:30