我正在尝试同时从两个单独的任务更新进度条。我已经尝试了很多方法,但没有取得多大成功。见下面的完整代码示例。在WPF中,添加一个进度条,将Maximum绑定到TextMax,将Value绑定到TextProgress,您会注意到进度条只填充到大约一半。
注意:这不是我的实际解决方案,只是我正在做的一个示例,它显示了我扔在一起的问题,请忽略代码样式/模式问题。
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
namespace DelegateTesting
{
public partial class MainWindow : Window
{
ResultsItemViewModel _ViewModel = new ResultsItemViewModel();
public MainWindow()
{
InitializeComponent();
DataContext = _ViewModel;
TextProcessing();
}
private static void Method1(
Action<int> reportProgress)
{
var progress = 0;
for(int i = 0;i<100;i++)
{
//Thread.Sleep(200);
reportProgress?.Invoke(++progress);
}
}
private static void Method2(
Action<int> reportProgress)
{
var progress = 0;
for (int i = 0; i < 100; i++)
{
//Thread.Sleep(200);
reportProgress?.Invoke(++progress);
}
}
private async Task TextProcessing()
{
_ViewModel.TextMax += 100;
_ViewModel.TextMax += 100;
var dispatcher = Application.Current.Dispatcher;
var reportProgress = dispatcher.MakeInvoker<int>(p => _ViewModel.TextProgress = p);
await Task.WhenAll(
Task.Run(() => Method1(reportProgress)),
Task.Run(() => Method2(reportProgress)));
}
}
public static class DispatcherHelper
{
public static Action<T> MakeInvoker<T>(
this Dispatcher dispatcher,
Action<T> action,
DispatcherPriority priority = DispatcherPriority.Normal)
{
return o => dispatcher.BeginInvoke(priority, action, o);
}
}
public class ResultsItemViewModel : INotifyPropertyChanged
{
int _textProgress, _textMax;
public int TextProgress
{
get => _textProgress;
set
{
_textProgress = value;
NotifyPropertyChanged();
}
}
public int TextMax
{
get => _textMax;
set
{
_textMax = value;
NotifyPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
var handler = PropertyChanged;
handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
答案 0 :(得分:1)
您没有等待TextProcessing
。你不能只在中间拨打await
。您可以一直异步或根本不同步。
此外,在构造函数中工作不是一个好习惯。
为了使其正常工作,您必须允许WPF
为您处理异步调用。我假设你想在有人做某事时开始行动,例如:
protected async void Button_OnClick(Object sender, EventArgs e)
{
await TextProcessing();
}
您始终可以将其绑定到启动窗口或类似事件的事件。
说实话,你的代码对我来说很不清楚,所以这可能会帮助你理解你真正需要的东西:
int _textProgress, _textMax;
public int TextProgress
{
get => _textProgress;
set
{
_textProgress = value;
NotifyPropertyChanged();
}
}
public int TextMax
{
get => _textMax;
set
{
_textMax = value;
NotifyPropertyChanged();
}
}
protected async void Button_OnClick(Object sender, EventArgs e)
{
TextMax = 0;
var t1 = Task.Run(() => {
TextProgress += 50;
});
var t2 = Task.Run(() => {
TextProgress += 50;
});
await Task.WhenAll(t1, t2);
}
在你的视图中,你应该有一些带有Button_OnClick
和进度条命令的按钮:
<ProgressBar Maximum="100" Height="50" Value="{Binding TextProgress}"></ProgressBar>
还有一件事。看起来你有一个ViewModel,但你正在视图中工作。您应该将该逻辑移动到ViewModel。