这是启动匿名任务并继续 ui 线程的好方法吗?
Is this a good way to start a anonymous task and continue with ui thread?
自从我处理任务和 lambda 表达式以来已经有一段时间了。这是 运行 使用 lambda 表达式的匿名任务然后在任务完成后在 UI 线程上 运行 代码的好方法吗?
private void btn_mods_Click(object sender, RoutedEventArgs e)
{
function_buttons_stackpanel.IsEnabled = false;
Loading();
Task task = new Task(() => {
if (IsServiceIsUp() != false)
{
webServiceMods = JsonConvert.DeserializeObject(_webServiceResponse).mods;
webServiceBaseUrl = JsonConvert.DeserializeObject(_webServiceResponse).basePath;
Console.Write(webServiceBaseUrl);
}
});
task.Start();
task.ContinueWith((foo) =>
{
FinishedLoading();
function_buttons_stackpanel.IsEnabled = true;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
private void Loading()
{
img_loading.Visibility = Visibility.Visible;
}
private void FinishedLoading()
{
img_loading.Visibility = Visibility.Collapsed;
}
我试图直接链接 task.Start,但这给了我一个错误 Cannot Implicitly convert type void to System.Threading.Tasks.Task
。
基本上我想做的是将整个过程从头到尾串联起来。
Task task = new Task(() => {
if (IsServiceIsUp() != false)
{
webServiceMods = JsonConvert.DeserializeObject(_webServiceResponse).mods;
webServiceBaseUrl = JsonConvert.DeserializeObject(_webServiceResponse).basePath;
Console.Write(webServiceBaseUrl);
}
}).Start();
在 PHP 我会做这样的事情:
$task = new Task(() => {
if (IsServiceIsUp() != false)
{
$webServiceMods = JsonConvert::DeserializeObject($_webServiceResponse).mods;
$webServiceBaseUrl = JsonConvert::DeserializeObject($_webServiceResponse).basePath;
Console::Write($webServiceBaseUrl);
}
})
->Start()
->ContinueWith(($foo) =>
{
FinishedLoading();
$function_buttons_stackpanel.IsEnabled = true;
}, TaskScheduler::FromCurrentSynchronizationContext());
这可能吗?如果是这样,有什么理由不这样做吗?如果有更好的方法可以举个例子吗?
谢谢!
您可以使用 async-await
:
private async void btn_mods_Click(object sender, RoutedEventArgs e)
{
if (!IsServiceIsUp())
return;
function_buttons_stackpanel.IsEnabled = false;
Loading();
await Task.Run(() =>
{
var result = JsonConvert.DeserializeObject(_webServiceResponse);
Console.Write(result.webServiceBaseUrl);
});
FinishedLoading();
function_buttons_stackpanel.IsEnabled = true;
}
就性能而言,我不太确定您是否需要使用线程池线程来反序列化 JSON。我肯定会测试此代码以确定它是否值得。
如果您将事件处理程序声明为异步函数,那么您不必启动任务,它已经异步运行。
All async functions should return Task instead of void and Task<TResult
> instead of TResult. The only exception is the event handler. The event handler returns void
在适当的异步等待中,这将如下所示:
private async void btn_mods_Click(object sender, RoutedEventArgs e)
{
function_buttons_stackpanel.IsEnabled = false;
Loading();
if (IsServiceIsUp())
{ // The service is up, start the deserialization
// because this function is async, you can call other async functions
// without having to start a task
// The UI remains responsive
webServiceMods = await JsonConvert.DeserializeObjectAsync(_webServiceResponse).mods;
// because of the await above, the second task is started after the first is finished:
webServiceBaseUrl = await JsonConvert.DeserializeObjectAsync(_webServiceResponse).basePath;
// because of the await the second task is also finished
Console.Write(webServiceBaseUrl);
FinishedLoading();
function_buttons_stackpanel.IsEnabled = true;
}
}
By making your event handler async your code will make full usage of async-await. Your code would look much neater without the magic of continueWith and other Task related functions from before the async-await era.
最后一点:下面的代码看起来很傻而且没有必要困难:
if (IsServiceIsUp() != false) ...
这当然应该是:
if (IsServiceIsUp()) ...
自从我处理任务和 lambda 表达式以来已经有一段时间了。这是 运行 使用 lambda 表达式的匿名任务然后在任务完成后在 UI 线程上 运行 代码的好方法吗?
private void btn_mods_Click(object sender, RoutedEventArgs e)
{
function_buttons_stackpanel.IsEnabled = false;
Loading();
Task task = new Task(() => {
if (IsServiceIsUp() != false)
{
webServiceMods = JsonConvert.DeserializeObject(_webServiceResponse).mods;
webServiceBaseUrl = JsonConvert.DeserializeObject(_webServiceResponse).basePath;
Console.Write(webServiceBaseUrl);
}
});
task.Start();
task.ContinueWith((foo) =>
{
FinishedLoading();
function_buttons_stackpanel.IsEnabled = true;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
private void Loading()
{
img_loading.Visibility = Visibility.Visible;
}
private void FinishedLoading()
{
img_loading.Visibility = Visibility.Collapsed;
}
我试图直接链接 task.Start,但这给了我一个错误 Cannot Implicitly convert type void to System.Threading.Tasks.Task
。
基本上我想做的是将整个过程从头到尾串联起来。
Task task = new Task(() => {
if (IsServiceIsUp() != false)
{
webServiceMods = JsonConvert.DeserializeObject(_webServiceResponse).mods;
webServiceBaseUrl = JsonConvert.DeserializeObject(_webServiceResponse).basePath;
Console.Write(webServiceBaseUrl);
}
}).Start();
在 PHP 我会做这样的事情:
$task = new Task(() => {
if (IsServiceIsUp() != false)
{
$webServiceMods = JsonConvert::DeserializeObject($_webServiceResponse).mods;
$webServiceBaseUrl = JsonConvert::DeserializeObject($_webServiceResponse).basePath;
Console::Write($webServiceBaseUrl);
}
})
->Start()
->ContinueWith(($foo) =>
{
FinishedLoading();
$function_buttons_stackpanel.IsEnabled = true;
}, TaskScheduler::FromCurrentSynchronizationContext());
这可能吗?如果是这样,有什么理由不这样做吗?如果有更好的方法可以举个例子吗?
谢谢!
您可以使用 async-await
:
private async void btn_mods_Click(object sender, RoutedEventArgs e)
{
if (!IsServiceIsUp())
return;
function_buttons_stackpanel.IsEnabled = false;
Loading();
await Task.Run(() =>
{
var result = JsonConvert.DeserializeObject(_webServiceResponse);
Console.Write(result.webServiceBaseUrl);
});
FinishedLoading();
function_buttons_stackpanel.IsEnabled = true;
}
就性能而言,我不太确定您是否需要使用线程池线程来反序列化 JSON。我肯定会测试此代码以确定它是否值得。
如果您将事件处理程序声明为异步函数,那么您不必启动任务,它已经异步运行。
All async functions should return Task instead of void and Task
<TResult
> instead of TResult. The only exception is the event handler. The event handler returns void
在适当的异步等待中,这将如下所示:
private async void btn_mods_Click(object sender, RoutedEventArgs e)
{
function_buttons_stackpanel.IsEnabled = false;
Loading();
if (IsServiceIsUp())
{ // The service is up, start the deserialization
// because this function is async, you can call other async functions
// without having to start a task
// The UI remains responsive
webServiceMods = await JsonConvert.DeserializeObjectAsync(_webServiceResponse).mods;
// because of the await above, the second task is started after the first is finished:
webServiceBaseUrl = await JsonConvert.DeserializeObjectAsync(_webServiceResponse).basePath;
// because of the await the second task is also finished
Console.Write(webServiceBaseUrl);
FinishedLoading();
function_buttons_stackpanel.IsEnabled = true;
}
}
By making your event handler async your code will make full usage of async-await. Your code would look much neater without the magic of continueWith and other Task related functions from before the async-await era.
最后一点:下面的代码看起来很傻而且没有必要困难:
if (IsServiceIsUp() != false) ...
这当然应该是:
if (IsServiceIsUp()) ...