4

I have async methods that returns an objects

public static IEnumerable<Users.User> GetUsers(IEnumerable<string> uids, Field fields)
{
    Task<ResponseApi<Users.User>>[] tasks;
    tasks = uids.Select(uid =>
    {
        var parameters = new NameValueCollection
        {
        {"uids", uid},
        {"fields", FieldsUtils.ConvertFieldsToString(fields)}
        };
        return GetUserResponseApi(parameters);
    }).ToArray();
    Task.WaitAll(tasks);
    foreach(Task<ResponseApi<Users.User>> task in tasks)
    {
        if(task.Result.Response != null)
        {
            yield return task.Result.Response;
        }
    }
}

And I want to update UI in other method,UI maybe don't update because method GetUserResponseApi don't return any value.

 public static Task<ResponseApi<Users.User>> GetUserResponseApi(NameValueCollection parameters)
    {
      return CallMethodApi("users.get", parameters, CallType.HTTPS)
            .ContinueWith(
            r =>
            {
//don't execute
                var responseApi = new ResponseApi<Users.User>();
                responseApi.Response = JsonConvert.DeserializeObject<Users.User>(r.Result["response"][0].ToString());
                return responseApi;

            });
    }

    private void BtnGetUsersClick(object sender, EventArgs e)
    {
        var random = new Random();
        int max = 175028595;
        var uids = new List<string>();
        for(int i = 1; i <= 20; i++)
        {
            uids.Add((random.Next(max) + 1).ToString());

        }
        Task.Factory.StartNew(() =>
                                  {
                                      var users = VkontakteApi.GetUsers(uids, Field.Online);
                                      foreach(var user in users)
                                      {
                                          richTextBox1.Text += string.Format("ID:{0} online:{1}", user.uid,
                                                                             user.online);
                                      }
                                  }, CancellationToken.None, TaskCreationOptions.None, _uiContext);
    }

How to resolve problem with ContinueWith in GetUserResponseApi?

UPDATE: I think that problem in method GetUserResponseApi because block ContinueWith doesn't execute.

svick
  • 236,525
  • 50
  • 385
  • 514
BILL
  • 4,711
  • 10
  • 57
  • 96

2 Answers2

3

Use Application.Current.Dispatcher to dispatch calls to UI thread whenever you access UI objects.

Application.Current.Dispatcher.Invoke(() => {
try
{
richTextBox1.Text += string.Format("ID:{0} online:{1}", user.uid, user.online);
}
catch
{
   //handle
}
), DispatcherPriority.Background);
Sergei B.
  • 3,227
  • 19
  • 18
  • Wow, I never knew about this! Will it work if it's in a separate/background thread/task? – matthewr Jun 22 '12 at 12:27
  • 1
    Yep. Dispatcher was created especially for this purpose, to update UI from background threads. – Sergei B. Jun 22 '12 at 12:40
  • Where is Current ? [msdn](http://msdn.microsoft.com/en-us/library/system.windows.forms.application_properties) – BILL Jun 22 '12 at 13:04
  • @Victor You didn't specify what UI library you're using, so invisible assumed you're using WPF. – svick Jun 22 '12 at 13:12
  • 1
    Yep, I assumed this is WPF. But you could still use Dispatcher in WinForms. You need to reference WindowsBase library in your project. Same question was answered here: http://stackoverflow.com/a/4429009/166584 – Sergei B. Jun 22 '12 at 13:49
  • @invisible Why would you use `Dispatcher` in Winforms when you can use `Control.Invoke()`? – svick Jun 22 '12 at 14:35
2

Try using TaskScheduler.FromCurrentSynchronizationContext() method:

Task.Factory.StartNew(() =>
  {
      var users = VkontakteApi.GetUsers(uids, Field.Online);
      foreach(var user in users)
      {
          richTextBox1.Text += string.Format("ID:{0} online:{1}", user.uid,
                                             user.online);
      }
  }, CancellationToken.None,
     TaskScheduler.FromCurrentSynchronizationContext());
svick
  • 236,525
  • 50
  • 385
  • 514
Ribtoks
  • 6,634
  • 1
  • 25
  • 37
  • `GetUsers()` is the method that takes a long time, running it on the UI thread is a terrible idea. – svick Jun 22 '12 at 13:15