I am working on an windows phone 8 app. I have to save video into camera roll folder.
To get a file stream for camera roll folder, I am using following function:
[CLSCompliantAttribute(false)]
public static Task<Stream> OpenStreamForWriteAsync(
this IStorageFile windowsRuntimeFile
)
For example:
Stream videoStream = await file.OpenStreamForWriteAsync();
where file is StorageFile.
I want to remove this await and make function synchronous because of requirements.
EDIT:
PS: I am executing this function on different thread and I want that thread to be synchronous. I want to write on that file stream after it is created.
Simply access Result:
Stream videoStream = file.OpenStreamForWriteAsync().Result;
This will block until the task finished its execution.
Please note that this can result in a deadlock of your program, if that code is executed on the UI thread.
Please refer to this blog post for further information.
Related
I have the following C# code:
var response = client.GetAsync(uri).Result;
MemoryStream stream = new MemoryStream();
response.Content.CopyToAsync(stream);
System.Console.WriteLine(stream.Length);
When I insert a breakpoint before the first statement and then continue the program, the code works fine and over 4 MB of data gets stored in the stream.
But if I run the program without any breakpoints or inserting the breakpoint after the after the first statement shown above, the code runs but no data or only 4 KB of data gets stored in the stream.
Can someone please explain why this is happening?
Edit:
Here is what I am trying to do in my program. I use couple of HttpClient.PostAsync requests to get a uri to download a wav file. Then I want to download the wav file into a memory stream. I don't know of any other ways to do this yet.
It seems like you are basically messing the flow of async and await.
The async call will be waited to complete and recapture the task when you use await keyword.
The mentioned code does not clarify whether you are using the async signature in your method or not. Let me clarify the solution for you
Possible solution 1:
public async Task XYZFunction()
{
var response = await client.GetAsync(uri); //we are waiting for the request to be completed
MemoryStream stream = new MemoryStream();
await response.Content.CopyToAsync(stream); //The call will wait until the request is completed
System.Console.WriteLine(stream.Length);
}
Possible solution 2:
public void XYZFunction()
{
var response = client.GetAsync(uri).Result; //we are running the awaitable task to complete and share the result with us first. It is a blocking call
MemoryStream stream = new MemoryStream();
response.Content.CopyToAsync(stream).Result; //same goes here
System.Console.WriteLine(stream.Length);
}
I have to create a Windows application where i will upload multiple file to azure file share storage and i need to show the multiple file upload progress using progress bar control in windows for application.
I want to show the dynamic progress bar on windows form with each upload iteration of file upload.
Can any one suggest with sample loop iteration for upload with multiple file using progress bar on windows form.
Assuming you are referring to Blob Storage.
UploadFromFileAsync(String, AccessCondition, BlobRequestOptions, OperationContext, IProgress, CancellationToken)
A IProgress object to handle StorageProgress messages.
StorageProgress Class
Holds information about the progress data transfers for both request
and response streams in a single operation.
A nice little example on their site, allbeit a stream example
CancellationToken cancellationToken = new CancellationToken();
IProgress<StorageProgress> progressHandler = new Progress<StorageProgress>(
progress => Console.WriteLine("Progress: {0} bytes transferred", progress.BytesTransferred)
);
await blob.UploadFromStreamAsync(
srcStream,
default(AccessCondition),
default(BlobRequestOptions),
default(OperationContext),
progressHandler,
cancellationToken
);
So where to from here. Because this is IO bound work its best not use Parallel.For or Parallel.ForEach its a waste of resources.
However, ActionBlock Class in the TPL dataflow can be suited, or just async/await pattern with Task.WaitAll Method.
Dataflow example
var block = new ActionBlock<MySomething>(
mySomething => MyMethodAsync(mySomething),
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 50 });
foreach (var something in ListOfSomethings)
{
block.Post(something );
}
block.Complete();
await block.Completion;
So without writing the rest of the code for you
Simply add up the size in bytes of your files before you start youy transfers.
Create your progress handlers, and associate them with your tasks
Possibly keep the transferred amount with your tasks
On progress (in thread safe manner) or just on a timmer (in a thread safe manner) sum your progress against the expected amount
Obviously there are details left out of here, however you are now a programmer and its your mission (if you choose to accept it) to figure it out.. free lunch given, and i look forward to your next questions about everything in between :)
I wrote a little winforms application that search for files on the disk (what file is not that important for the sake of the question). the problem is the that it can be even 100,000 files or so. so this operation takes time.
What I want to achieve is to do the search operation as an async operation and not to block the UI thread so the form won't get stuck.
I can do this with the backgroundWorker but for some reason not with the async\await mechanism.
Here is my code:
private async void button_FindFiles_Click(object sender, EventArgs e)
{
await SearchFilesUtil.SearchPnrFilesAsync(this.textBox_mainDirectory.Text);
MessageBox.Show("After SearchPnrFilesAsync");
}
public async static Task SearchPnrFilesAsync(string mainDir)
{
foreach (string file in Directory.EnumerateFiles(mainDir, ".xml", SearchOption.AllDirectories))
{
var fileContenet = File.ReadAllText(file);
var path = Path.Combine(#"C:\CopyFileHere", Path.GetFileName(file));
using (StreamWriter sw = new StreamWriter(path))
{
await sw.WriteAsync(fileContenet);
}
}
}
Why is the UI thread get stuck and not displaying the MessageBox immediately?
what am I missing ?
The fact of marking SearchPnrFilesAsync with async keyword itself doesn't magically starts execution ot this method asynchronously in separate task.
In fact, all of the code in SearchPnrFilesAsync except sw.WriteAsync executes in UI thread thus blocking it.
If you need to execute your whole method in separate task, you can do it by wrapping like:
public async static Task SearchPnrFilesAsync(string mainDir)
{
await Task.Run(() => your_code_here);
}
Why does the UI thread get stuck?
Probably because you have some blocking work done on the UI thread, such as reading a file.
Why is my MessageBox not displayed immediately?
Because that is not how async works. When you await a method, it asynchronously yields control to the caller until the operation is done. When the first await is hit, you start reading files from disk and copying them. await does not mean "execute this on a different thread and continue".
What you probably want to do is use an asynchronous reading mechanism instead of the blocking File.ReadAllText. You can do this using StreamReader:
public static async Task SearchPnrFilesAsync(string mainDir)
{
foreach (string file in Directory.EnumerateFiles(mainDir, ".xml",
SearchOption.AllDirectories))
{
var path = Path.Combine(#"C:\CopyFileHere", Path.GetFileName(file));
using (var reader = File.OpenRead(file))
using (var writer = File.OpenWrite(path))
{
await reader.CopyToAsync(writer);
}
}
}
Why is the UI thread get stuck
I've tested the code you posted doesn't make UI blocked.
When SearchPnrFilesAsync running, I was able to resize the window and click the button as well.
Did you think it was blocked because it didn't show the "After SearchPnrFilesAsync" message? If Something I wrong, please let me know.
not displaying the MessageBox immediately
The await keyword inside the button_FindFiles_Click function asynchronously waits for the SearchFilesUtil.SearchPnrFilesAsync function to finish.
That's why "After SearchPnrFilesAsync" message doesn't pop up as soon as the button is clicked.
If you want the SearchFilesUtil.SearchPnrFilesAsync function to be executed as soon as you click the button
and immediately you want to check the message, you can call the method without await keyword.
SearchFilesUtil.SearchPnrFilesAsync(this.textBox_mainDirectory.Text);
When you don't use await on a function that returns a Task, you'll get a "warning".
In this case, use discards feature and the warning will disappear. (With C# 7)
_ = SearchFilesUtil.SearchPnrFilesAsync(this.textBox_mainDirectory.Text);
If you want to know more about it, please check out this link (
https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/functional/discards)
I'm attempting to load and read a settings file on application launch, and about 90% of the time, the await GetFileAsync("filename.xml"); never returns, thus, hanging the application.
About a quarter of the time, if I step through the code, it'll actually return and read the file.
Here's a very simplified version of the code:
App.xaml.cs:
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
FileLoader.Load().Wait();
// File-load dependent stuff
}
FileLoader.cs:
public async static Task Load()
{
StorageFolder folder = ApplicationData.Current.LocalFolder;
StorageFile file;
bool fileExists = true;
try
{
// The following line (often) never returns
file = await folder.GetFileAsync("filename.xml");
{
catch
{
fileExists = false;
}
// Do stuff with loaded file
}
If I watch the Output window in Visual Studio, after awhile of waiting I get "The thread '<No Name>' (0x30c) has exited with code 0 (0x0)."
Does anyone have any idea of what's happening here?
By default, when you await a Task that has not yet completed, the method resumes on a captured context (in this case, the UI context).
So, here's why your code is failing:
OnLaunched calls Load (within the UI context).
Load awaits. This causes the Load method to return an incomplete task and schedule its completion for later. This continuation is scheduled for the UI context.
OnLaunched blocks on the task returned from Load. This blocks the UI thread.
GetFileAsync eventually completes, and attempts to run the continuation for Load.
The continuation for Load waits for the UI thread to be available so it can execute in the UI context.
At this point, OnLaunched is waiting for Load to complete (blocking the UI thread by doing so), and Load is waiting for the UI thread to be free. Deadlock.
These best practices avoid this situation:
In your "library" async methods, use ConfigureAwait(false) whenever possible. In your case, this would change await folder.GetFileAsync("filename.xml"); to await folder.GetFileAsync("filename.xml").ConfigureAwait(false);.
Don't block on Tasks; it's async all the way down. In other words, replace Wait with await.
For more information:
Await, and UI, and deadlocks! Oh, my!
My async/await intro post, which includes a brief description of how Task awaiters use SynchronizationContext and introduces some best practices.
The Async/Await FAQ, which goes into more detail on the contexts.
This MSDN forum post.
Stephen Toub demos this deadlock, and so does Lucian Wischik.
Update, 2012-07-13: Incorporated this answer into a blog post.
I am writing a simple metro app. However, the API blocks when accessing files. By blocking, I mean the programs waits forever. Creating/opening a file or folder should take at most a few seconds. In this case, it takes forever.
When I run the program, it never comes back from OnTest. Is it what you get.
I understand .Wait will wait for the creation of files and folders to finishe. Maybe that's not great design. However, that's not the point.
My question is:
Do you get the same behavior (blocks the program forever)
Is it what's supposed to happen or is it a bug in WinRT? (I am using the consumer preview)
If that's the expected behavior, why does it take forever?
Here is the XAML code:
<Button Click="OnTest">Test</Button>
Here is the C# code:
private async void OnTest(object sender, RoutedEventArgs e)
{
var t = new Cache("test1");
t = new Cache("test2");
t = new Cache("test3");
}
class Cache
{
public Cache(string name)
{
TestRetrieve(name).Wait();
}
public static async Task TestRetrieve(string name)
{
StorageFolder rootFolder = ApplicationData.Current.LocalFolder;
var _folder = await rootFolder.CreateFolderAsync(name, CreationCollisionOption.OpenIfExists);
var file = await _folder.CreateFileAsync("test.xml", CreationCollisionOption.OpenIfExists);
}
}
It blocks on the second call to new Cache("test2");
I have not attempted to run your program or reproduce your problem, but I can make an educated guess as to what is going on.
Suppose you wrote yourself the following to-do list:
Put a letter to mom in the mailbox.
Set the alarm to wake me up as soon as I've read her reply.
Go to sleep.
Check the mailbox for the reply.
Read the reply.
Now do everything on that list strictly in order from top to bottom. What happens?
The problem is not with the post office or with mom; they are picking up the letter you put in the mailbox, sending it to mom, mom is writing her reply and the post office is bringing it back to you. The problem is that you never get to the fourth step because you only can start the fourth step after you complete the fifth step and the alarm wakes you up. You'll sleep forever because you are essentially waiting for your future self to wake your present self up.
Eric, Thank you for the explanation.
You're welcome.
However, I am still confused as to why my code does not work.
OK, let's break it down. What does your program really do? Let's simplify:
void M()
{
Task tx = GetATask();
tx.Wait();
}
async Task GetATask()
{
Task ty = DoFileSystemThingAsync();
await ty;
DoSomethingElse();
}
First off: what is a task? A task is an object that represents (1) a job to be done, and (2) a delegate to the continuation of the task: the thing that needs to happen after the task is done.
So you call GetATask. What does it do? Well, the first thing it does is it makes a Task and stores it in ty. That task represents the job "start some operation on the disk, and notify the I/O completion thread when it is done".
What is the continuation of that task? What has to happen after that task is done? DoSomethingElse needs to be called. So the compiler transforms the await into a bunch of code that tells the task to ensure that DoSomethingElse is called when the task is done.
The moment that the continuation of the I/O task has been set, the method GetATask returns a task to the caller. What task is that? This is a different task than the task that got stored into ty. The task that is returned is the task that represents the job do everything that the method GetATask needs to do.
What is the continuation of that task? We don't know! That is up to the caller of GetATask to decide.
OK, so let's review. We have two task objects. One represents the task "go do this thing on the file system". It will be done when the file system does its work. It's continuation is "call DoSomething". We have a second task object that represents the job "do everything in the body of GetATask". It will be done after the call to DoSomethingElse returns.
Again: the first task will be complete when the file I/O succeeds. When that happens, the file I/O completion thread will send a message to the main thread saying "hey, that file I/O you were waiting for is done. I am telling you this because it is now time for you to call DoSomethingElse".
But the main thread is not examining its message queue. Why not? Because you told it to synchronously wait until everything in GetATask, including DoSomethingElse, is complete. But the message that is telling you to run DoSomethingElse now cannot be processed because you are waiting for DoSomethingElse to be complete.
Now is it clear? You are telling your thread to wait until your thread is done running DoSomethingElse before you check to see if "please call DoSomethingElse" is in the queue of work to be performed on this thread! You are waiting until you have read the letter from mom, but the fact that you are waiting synchronously means that you are not checking your mailbox to see if the letter has arrived.
Calling Wait is obviously wrong in this case because you are waiting for yourself to do something in the future, and that's not going to work. But more generally, calling Wait completely negates the entire point of being async in the first place. Just don't do that; it doesn't make any sense to say both "I want to be asynchronous" and "but I want to synchronously wait". Those are opposites.
You're using Wait() in the constructor of the Cache class. That's going to block until whatever is currently executing asynchronously has finished.
This is not the way to design this. Constructors and async do not make sense. Perhaps a factory method approach like this would work better:
public class Cache
{
private string cacheName;
private Cache(string cacheName)
{
this.cacheName = cacheName;
}
public static async Cache GetCacheAsync(string cacheName)
{
Cache cache = new Cache(cacheName);
await cache.Initialize();
return cache;
}
private async void Initialize()
{
StorageFolder rootFolder = ApplicationData.Current.LocalFolder;
var _folder = await rootFolder.CreateFolderAsync(this.cacheName, CreationCollisionOption.OpenIfExists);
var file = await _folder.CreateFileAsync("test.xml", CreationCollisionOption.OpenIfExists);
}
}
And then you use it like this:
await Task.WhenAll(Cache.GetCacheAsync("cache1"), Cache.GetCacheAsync("cache2"), Cache.GetCacheAsync("cache3"));
TestRetrieve(name).Wait();
You're telling it to block specifically by using the .Wait() call.
Remove the .Wait() and it shouldn't block anymore.
The existing answers provide very thorough explanations of why it blocks and code examples of how to make it not block, but these many be 'more information' than some users understand. Here is a simpler 'mechanics oriented' explanation..
The way the async/await pattern works, each time you await an async method, you are "attaching" that method's async context to the current method's async context. Imagine await as passing in a magic hidden paramater "context". This context-paramater is what allows nested await calls to attach to the existing async context. (this is just an analogy...the details are more complicated than this)
If you are inside an async method, and you call a method synchronously, that synchronous method doesn't get that magic hidden async context paramater, so it can't attach anything to it. It's then an invalid operation to create a new async context inside that method using 'wait', because the new context does not get attached to your thread's existing top-level async context (because you don't have it!).
Described in terms of the code-example, the TestRetrieve(name).Wait(); is not doing what you think it's doing. It's actually telling the current thread to re-enter the async-activity-wait-loop at the top. In this example, this is the UI-thread, which is called your OnTest handler. The following picture may help:
UI-thread context looks like this...
UI-Thread ->
OnTest
Since you didn't have a connected chain of await/async calls all the way down, you never "attached' the TestRetrieve async context to the above UI-Thread async chain. Effectively, that new context you made is just dangling off in nowhere land. So when you "Wait" the UIThread, it just goes right back to the top.
For async to work, you need to keep a connected async/await chain from the top-level synchronous thread (in this case it's the UI-thread doing this) through all async actions you need to do. You can't make a constructor async, so you can't chain an async context into a constructor. You need to construct the object synchronously and then await TestRetrieve from outside. Remove the 'Wait' line from your constructor and do this...
await (new Cache("test1")).TestRetrieve("test1");
When you do this, the 'TestRetrieve' async context is properly attached, so the chain looks like this:
UI-Thread ->
OnTest ->
TestRetrieve
Now the UI-thread async-loop-handler can properly resume TestRetrieve during async completions and your code will work as expected.
If you want to make an 'async constructor', you need to do something like Drew's GetCacheAsync pattern, where you make a static Async method which constructs the object synchronously and then awaits the async method. This creates the proper async chain by awaiting and 'attaching' the context all the way down.