wpf c# 后台工作者在执行完成时工作
wpf c# background worker works when execution finished
我有一个 wpf 应用程序,我想在任务之前启动加载指示器并在任务完成后结束。但是指标在任务执行后启动。
我正在尝试的是如下。
private void RunAllScriptsChildwdwBtnOK_Click(object sender, RoutedEventArgs e)
{
worker.RunWorkerAsync(); // this supposed to start progress bar
_RunAllScripts_Click();
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
this.Dispatcher.Invoke(() =>
{
... Start loading indicator
});
}
private void worker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
... End loading indicator
}
但加载指示器仅在
_RunAllScripts_Click();方法执行完毕。
(我发现在取消订阅 worker_RunWorkerCompleted 事件后,进度条开始并保持原样,因为没有代码可以结束它)。
我还想补充一点,断点在执行前命中 worker_DoWork 方法,但 UI 在执行后更新,如我上面所述。
感谢您提供的所有帮助。
如果我是你,我会为此使用 async + await 关键字
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
// this is where you would enable your indicator
Button.IsEnabled = false;
await Task.Run(
() =>
{
// this is where you put your work, which should be executed in the background thread.
Thread.Sleep(2000);
});
// this is where you would disable it
Button.IsEnabled = true;
}
使用 async/await
即可。 await
关键字将允许您 运行 在没有 affecting/blocking UI 线程的情况下工作(允许消息泵送仍然发生)。工作完成后,将执行 await
关键字后的任何代码。
请注意,我还将 await
工作包含在 InvokeAsync
调用中,因为您正在进行的额外工作似乎需要 UI 线程访问权限。
private async void RunAllScriptsChildwdwBtnOK_Click(object sender, RoutedEventArgs e)
{
//TODO ... Start loading indicator
await Task.Run(async ()=>
{
await Application.Current.Dispatcher.InvokeAsync(()=>
{
_RunAllScripts_Click();
});
});
//TODO ... End loading indicator
}
亲爱的好心人帮助我解决这个问题,谢谢大家。
这对我有用,希望对所有人有用。
BackgroundWorker bwTestAll = new BackgroundWorker() { WorkerReportsProgress = true };
bwTestAll.DoWork += new DoWorkEventHandler(TestAll);
bwTestAll.RunWorkerCompleted += TestAll_RunWorkerCompleted;
//this is where I initialize my loading ring and other stuff and marshall background
//worker to do the main work
Dispatcher.Invoke(new Action(() =>
{
EnableLoading = true;
RunAllScriptsTest.IsEnabled = false;
}), DispatcherPriority.ContextIdle);
bwTestAll.RunWorkerAsync();
//this is my main work
void TestAll(object sender, DoWorkEventArgs e)
{
presenter.RunAllScripts(true);
}
//this is where I do my post-work stuff
private void TestAll_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
Dispatcher.Invoke(new Action(() =>
{
/
EnableLoading = false;
RunAllScriptsTest.IsEnabled = true;
DbExecGrid = this.ExecutionResults;
ShowOrHideExecGrid(this.EnableOrDisableGrid);
}), DispatcherPriority.ContextIdle);
}
*请注意,"DispatcherPriority.ContextIdle" 的 Dispatcher 适合我。
我有一个 wpf 应用程序,我想在任务之前启动加载指示器并在任务完成后结束。但是指标在任务执行后启动。 我正在尝试的是如下。
private void RunAllScriptsChildwdwBtnOK_Click(object sender, RoutedEventArgs e)
{
worker.RunWorkerAsync(); // this supposed to start progress bar
_RunAllScripts_Click();
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
this.Dispatcher.Invoke(() =>
{
... Start loading indicator
});
}
private void worker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
... End loading indicator
}
但加载指示器仅在 _RunAllScripts_Click();方法执行完毕。 (我发现在取消订阅 worker_RunWorkerCompleted 事件后,进度条开始并保持原样,因为没有代码可以结束它)。
我还想补充一点,断点在执行前命中 worker_DoWork 方法,但 UI 在执行后更新,如我上面所述。
感谢您提供的所有帮助。
如果我是你,我会为此使用 async + await 关键字
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
// this is where you would enable your indicator
Button.IsEnabled = false;
await Task.Run(
() =>
{
// this is where you put your work, which should be executed in the background thread.
Thread.Sleep(2000);
});
// this is where you would disable it
Button.IsEnabled = true;
}
使用 async/await
即可。 await
关键字将允许您 运行 在没有 affecting/blocking UI 线程的情况下工作(允许消息泵送仍然发生)。工作完成后,将执行 await
关键字后的任何代码。
请注意,我还将 await
工作包含在 InvokeAsync
调用中,因为您正在进行的额外工作似乎需要 UI 线程访问权限。
private async void RunAllScriptsChildwdwBtnOK_Click(object sender, RoutedEventArgs e)
{
//TODO ... Start loading indicator
await Task.Run(async ()=>
{
await Application.Current.Dispatcher.InvokeAsync(()=>
{
_RunAllScripts_Click();
});
});
//TODO ... End loading indicator
}
亲爱的好心人帮助我解决这个问题,谢谢大家。 这对我有用,希望对所有人有用。
BackgroundWorker bwTestAll = new BackgroundWorker() { WorkerReportsProgress = true };
bwTestAll.DoWork += new DoWorkEventHandler(TestAll);
bwTestAll.RunWorkerCompleted += TestAll_RunWorkerCompleted;
//this is where I initialize my loading ring and other stuff and marshall background
//worker to do the main work
Dispatcher.Invoke(new Action(() =>
{
EnableLoading = true;
RunAllScriptsTest.IsEnabled = false;
}), DispatcherPriority.ContextIdle);
bwTestAll.RunWorkerAsync();
//this is my main work
void TestAll(object sender, DoWorkEventArgs e)
{
presenter.RunAllScripts(true);
}
//this is where I do my post-work stuff
private void TestAll_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
Dispatcher.Invoke(new Action(() =>
{
/
EnableLoading = false;
RunAllScriptsTest.IsEnabled = true;
DbExecGrid = this.ExecutionResults;
ShowOrHideExecGrid(this.EnableOrDisableGrid);
}), DispatcherPriority.ContextIdle);
}
*请注意,"DispatcherPriority.ContextIdle" 的 Dispatcher 适合我。