我有长时间的搜索操作,定期更新UI(找到出现 - >更新用户界面)
我试图通过多种方式实现它:
异步/ AWAIT
public void PushButton()
{
await AsyncSearchAll();
}
public async Task AsyncSearchAll(SearchPanelViewModel searchPanelViewModel, SearchSettings searchSettings, CancellationToken cancellationToken)
{
await Task.Factory.StartNew(() =>
{
//searching for occurence
//write it into panel
}, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}
BackgroundWorker的
我想使用它,但我不想只使用.ReportProgress()
调用Dispatcher.BeginInvoke(()=>{//updating UI})
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
var backgroundThread = new Thread(CountToTen)
{
IsBackground = true
};
backgroundThread.Start();
}
private void CountToTen()
{
for (int i = 1; i <= 10000; i++)
{
var j = i;
Dispatcher.BeginInvoke(new Action(() => Seconds.Text = j.ToString(CultureInfo.InvariantCulture)));
}
}
完成线程后写入所有数据的所有方法。 是否有任何方法可以运行后台任务,通过阻止ui来定期更新UI而不会减慢程序速度?
答案 0 :(得分:3)
最好是将“工人”逻辑与“UI更新”逻辑分开。
这样的事情:
public async Task AsyncSearchAll(SearchPanelViewModel searchPanelViewModel, SearchSettings searchSettings, CancellationToken cancellationToken)
{
while (..)
{
var results = await Task.Run(() => /* search more */);
/* update panel with results */
}
}
但是如果你想要实际的进展更新,也有办法做到这一点:
public async void PushButton()
{
Progress<MyUpdateType> progress = new Progress<MyUpdateType>(update =>
{
/* update panel */
});
await Task.Run(() => SearchAll(..., progress));
}
public void SearchAll(SearchPanelViewModel searchPanelViewModel,
SearchSettings searchSettings, CancellationToken cancellationToken,
IProgress<MyUpdateType> progress)
{
while (..)
{
/* search more */
if (progress != null)
progress.Report(new MyUpdateType(...));
}
}
答案 1 :(得分:0)
我认为在这种情况下,最好是使用绑定。使用new collection synchronization,您可以执行从其他线程添加到绑定ObservableCollection<T>
的操作。
如果这对您的目的不够,只要您在另一个线程上产生一些结果,就可以使用Progress<T>
在UI线程上执行操作(但顾名思义,Progress
是主要用于进度报告)。
如果不适合,您可以使用TPL Dataflow。您将为UI调度程序设置一个ActionBlock<T>
并设置TaskScheduler
。您的工作线程会将生成的项目发送到块,块将在UI线程上处理它们。