我有返回对象的异步方法
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;
}
}
}
我想用其他方法更新UI,UI可能不会更新,因为方法GetUserResponseApi不返回任何值。
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);
}
如何解决GetUserResponseApi
中的ContinueWith问题?
更新
我认为方法GetUserResponseApi
中的问题因为块ContinueWith没有执行。
答案 0 :(得分:3)
每当您访问UI对象时,都使用Application.Current.Dispatcher
来调度UI线程。
Application.Current.Dispatcher.Invoke(() => {
try
{
richTextBox1.Text += string.Format("ID:{0} online:{1}", user.uid, user.online);
}
catch
{
//handle
}
), DispatcherPriority.Background);
答案 1 :(得分:2)
尝试使用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());