使用 Async/Await 时的 WPF ProgressBar 用法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26285926/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF ProgressBar usage when using Async/Await
提问by user1166905
I have a very simple task that loads some data like so:
我有一个非常简单的任务,它加载一些数据,如下所示:
async Task<List<Invoice>> GetInvoices()
{
var invoices = await Task.Run(() => db.Invoices.AsNoTracking().ToList());
return invoices;
}
What would be the best way to use this with a progressbar? I don't need to get the percentage loaded (although that would be useful), I simply need to show/hide the progressbar at start and finish of loading data. Is there a way to create a completed or finished method perhaps?
将它与进度条一起使用的最佳方法是什么?我不需要加载百分比(尽管这很有用),我只需要在加载数据的开始和结束时显示/隐藏进度条。有没有办法创建一个完成或完成的方法?
I am very new to async/await so kid gloves please!
我对 async/await 很陌生,所以请戴手套!
回答by Sebastian Negraszus
Assuming GetInvoicesgets called in some UI event handler and there is some progress bar control called ProgressBar, it's really simple:
假设GetInvoices在一些 UI 事件处理程序中被调用,并且有一些名为 的进度条控件ProgressBar,它真的很简单:
private async void OnButton1Click(..)
{
ProgressBar.IsIndeterminate = true;
var result = await GetInvoices();
ProgressBar.IsIndeterminate = false; // Maybe hide it, too
// TODO: Do stuff with result
}
If you want to show actual progress, take a look at Progress<T>and IProgress<T>.
如果您想显示实际进度,请查看Progress<T>和IProgress<T>。
回答by Patrick
You already have what you need. To illustrate here's a simple example with tasks and using await, and ContinueWith.
你已经有了你需要的东西。为了说明这里有一个简单的例子,任务和使用 await 和 ContinueWith。
using System;
using System.Threading.Tasks;
using System.Diagnostics;
public class Program
{
public static void Main()
{
Task t = new Program().TestTasks();
Console.WriteLine("hello");
t.Wait();
}
public async Task TestTasks()
{
Stopwatch watch = Stopwatch.StartNew();
Console.WriteLine("1." + watch.ElapsedMilliseconds);
// await task
int res = await TestAsync();
Console.WriteLine("2." + watch.ElapsedMilliseconds + " " + res);
// save task and wait on it
Task<int> t = TestAsync();
t.ContinueWith((r) =>
{
Console.WriteLine("4." + watch.ElapsedMilliseconds + " " + r.Result);
});
Console.WriteLine("3." + watch.ElapsedMilliseconds);
t.Wait();
}
public static async Task<int> TestAsync()
{
await Task.Delay(TimeSpan.FromSeconds(2));
return 42;
}
}
This prints:
这打印:
1.0 hello 2.2009 42 3.2009 4.4013 42
1.0 hello 2.2009 42 3.2009 4.4013 42
Note how the await leaves the method and prints "hello" in the Main method, and after (about) 2 seconds continue in the TestTasks method. On the other hand, if we do notawait, as the second call to TestAsync shows, 3. is printed immediately, and after 2 seconds, 4. is printed.
请注意 await 如何离开该方法并在 Main 方法中打印“hello”,并在(大约)2 秒后在 TestTasks 方法中继续。另一方面,如果我们不等待,如对 TestAsync 的第二次调用所示, 3. 立即打印,2 秒后, 4. 打印。
With this in mind, you can just call your method GetInvoiceswith await since you're returning a Task.
考虑到这一点,您可以GetInvoices使用 await调用您的方法,因为您要返回一个任务。
// Set state of progressbar to indeterminate
List<Invoice> result = await GetInvoices();
// Set state of progressbar to nothing
回答by Tigran
You can do something like:
您可以执行以下操作:
var task = Task.Run(() => db.Invoices.AsNoTracking().ToList());
//show progress
task.ContinueWith(...CLOSE PROGRESS BAR...);
In practise you use Task.ContinueWithconstruct to catch the termination of the task and hide a progress bar you have shown before.
在实践中,您使用Task.ContinueWith构造来捕获任务的终止并隐藏您之前显示的进度条。
Note: keep in mind that acting on UI element from another thread requires Invoke()call, as that call redirects actual invokation to the main thread, which is a only thread were UI controls can be operated on windows.
注意:请记住,从另一个线程处理 UI 元素需要Invoke()调用,因为该调用将实际调用重定向到主线程,这是唯一一个可以在 Windows 上操作 UI 控件的线程。

