I'm trying to understand what the correct code to grab a set of data asynchronously when I do not have access to the client lib I am using to retrieve the data. I specify an endpoint and a date range and I'm supposed to retrieve a list of playlists. What I have now never comes back after the Start() call. Note: this is running in a WinForm. I am trying to better understand Tasks and don't just want to jump to awaits or a BackgroundWorker. I know I'm getting lost somewhere.
private void GoButtonClick(object sender, EventArgs e)
{
string baseUrl = "http://someserver/api";
var startDateTime = this._startDateTimePicker.Value;
var endDateTime = this._endDateTimePicker.Value;
_getPlaylistsFunc = delegate()
{
var client = new PlaylistExportClient(baseUrl);
return client.GetPlaylistsByDateRange(startDateTime, endDateTime).ToList();
};
var task = new Task<List<Playlist>>(_getPlaylistsFunc);
task.ContinueWith((t) => DisplayPlaylists(t.Result));
task.Start();
}
private void DisplayPlaylists(List<Playlist> playlists)
{
_queueDataGridView.DataSource = playlists;
}
UPDATE I made these changes but now the application seems to hang the UI thread.
private void GoButtonClick(object sender, EventArgs e)
{
string baseUrl = "http://someserver/api";
var startDateTime = this._startDateTimePicker.Value;
var endDateTime = this._endDateTimePicker.Value;
var token = Task.Factory.CancellationToken;
var context = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() =>
{
var client = new PlaylistExportClient(baseUrl);
_queueDataGridView.DataSource = client.GetPlaylistsByDateRange(startDateTime, endDateTime).ToList();
},token,TaskCreationOptions.None,context);
}
I recommend you use the Task-based Asynchronous Pattern. It's quite straightforward:
private async void GoButtonClick(object sender, EventArgs e)
{
string baseUrl = "http://someserver/api";
var startDateTime = this._startDateTimePicker.Value;
var endDateTime = this._endDateTimePicker.Value;
var playlists = await Task.Run(() =>
{
var client = new PlaylistExportClient(baseUrl);
return client.GetPlaylistsByDateRange(startDateTime, endDateTime).ToList();
});
_queueDataGridView.DataSource = playlists;
}
Note that this will block a threadpool thread; if you can modify the library to have a GetPlaylistsByDateRangeAsync
method, you can make this more efficient.
Edit: If you're stuck on .NET 4.0, you can install Microsoft.Bcl.Async to get full async
/await
capabilities. If - for some inexplicable reason - you still can't use async
/await
, then you can do it like this:
private void GoButtonClick(object sender, EventArgs e)
{
string baseUrl = "http://someserver/api";
var startDateTime = this._startDateTimePicker.Value;
var endDateTime = this._endDateTimePicker.Value;
var context = TaskScheduler.FromCurrentSynchronizationContext();
Task.Run(() =>
{
var client = new PlaylistExportClient(baseUrl);
return client.GetPlaylistsByDateRange(startDateTime, endDateTime).ToList();
}).ContinueWith(t =>
{
_queueDataGridView.DataSource = t.Result;
}, context);
}
However, note that your error handling is more complex with this approach.
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