dimanche 29 mars 2015

I've managed to implement a Task in my class UpdateManager that downloads a file from my webspace.



public async Task DownloadPackageTask(IProgress<int> progress)
{
var webRequest = WebRequest.Create(new Uri("http://ift.tt/1Cx3LkH"));
using (var webResponse = await webRequest.GetResponseAsync())
{
var buffer = new byte[1024];
FileStream fileStream = File.Create("Path"));
using (Stream input = webResponse.GetResponseStream())
{
int received = 0;
double total = 0d;
var size = GetFileSize(new Uri("...")); // Gets the content length with a request as the Stream.Length-property throws an NotSupportedException
if (size != null)
total = (long) size.Value;

int size = await input.ReadAsync(buffer, 0, buffer.Length);
while (size > 0)
{
fileStream.Write(buffer, 0, size);
received += size;
progress.Report((received/total)*100));
size = await input.ReadAsync(buffer, 0, buffer.Length);
}
}
}
}


This works well, the file is being downloaded and also if I add Debug.Print((received/total)*100) it outputs the correct percentage, everything is alright. The method is marked as async so that it can be awaited/wrapped asynchronously in a task. The problem occurs in another class UpdaterUi that is basically the interface between the manager and the user interface and calls the method like that:



public void ShowUserInterface()
{
TaskEx.Run(async delegate
{
var downloadDialog = new UpdateDownloadDialog
{
LanguageName = _updateManager.LanguageCulture.Name,
PackagesCount = _updateManager.PackageConfigurations.Count()
};

_context.Post(downloadDialog.ShowModalDialog, null); // Do this with a SynchronizationContext as we are not on the UI thread.

var progressIndicator = new Progress<int>();
progressIndicator.ProgressChanged += (sender, value) =>
downloadDialog.Progress = value;


await TaskEx.Run(() => _updateManager.DownloadPackageTask(progressIndicator));
});
}


It never calls the anonymous method there that should be invoked as soon as the progress changes, but nothing happens, I debugged it with breakpoints.


The problem is maybe that the progressIndicator is not created on the UI-thread, but on the new thread created by TaskEx.Run. It doesn't fire the event and consecutively the UI does not update the progressbar it contains (which it does in the setter of the Progress-property that is initialized above).


The problem is that I don't know what to do in order to make it working, how am I supposed to change the implementation in my project to get it working, is my thought of that threading problem correct?


Thanks in advance!


Aucun commentaire:

Enregistrer un commentaire