【发布时间】:2021-07-16 19:30:51
【问题描述】:
我一直在四处寻找有类似问题的人,但没有找到任何东西。我正在使用 WPF UI 编写 C# 应用程序。
要更新进度条,我不能像以前(在 CLI 中)那样使用多线程,因为它告诉我如果 UI 元素不是来自主线程,我就无法更新它。
一种解决方案是创建后台工作人员。我已经实现了这个解决方案并且效果很好,但是我希望将任务分配给更多的工作线程/线程(多线程)以提高效率。
我不知道我必须采取的方向。如果有人能指导我解决这个问题,那将更受欢迎。
这是我的代码:(用于使用 MVVM 模式进行编码,只是在这里粘贴我的代码对您来说更简单)
public partial class testFunctionTaskPanel: Page
{
private BackgroundWorker backgroundWorker1 = new BackgroundWorker();
private string myURL;
public testFunctionTaskPanel()
{
InitializeComponent();
}
private void startButton_Click(object sender, RoutedEventArgs e)
{
myURL = myURL.Text;
myResults.Items.Clear();
myResults.Items.Add("----Starting----");
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.ProgressChanged += ProgressChanged;
backgroundWorker1.DoWork += DoWork;
backgroundWorker1.RunWorkerCompleted += BackgroundWorker_RunWorkerCompleted;
backgroundWorker1.RunWorkerAsync();
}
private void DoWork(object sender, DoWorkEventArgs e)
{
int length = myLoadedList.Items.Count;
for (int i = 1; i <= length; i++)
{
try
{
HttpRequest req = new HttpRequest();
req.Proxy = null;
req.ConnectTimeout = 5000;
req.IgnoreProtocolErrors = true;
string get = myURL + myLoadedList.Items[i].ToString();
var response = req.Get(get);
if (response.StatusCode == Leaf.xNet.HttpStatusCode.OK)
{
this.Dispatcher.Invoke(() =>
{
myResults.Items.Add(myLoadedList.Items[i].ToString());
});
}
}
catch{}
backgroundWorker1.ReportProgress(i);
}
}
private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
myResults.Items.Add("----Finish----");
}
private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// This is called on the UI thread when ReportProgress method is called
progressbar.Value = e.ProgressPercentage;
}
}
【问题讨论】:
-
如果您使用任务和调用,您可能不需要
BackgroundWorker。请参阅docs.microsoft.com/en-us/dotnet/api/… Invoke 将阻止您在尝试从另一个线程更新进度条时看到的错误消息。 -
这个话题有很好的处理here。
-
BackgroundWorker 已弃用。在现代 Sharp 中,使用异步方法(async/await)和 Task 是正确的。
-
大部分问题都是你自己制造的。 WPF 中的常见做法是使用数据绑定而不是直接访问 UI 元素。使用绑定时,可以在任何线程中更改数据。
-
@RobertHarvey 非常感谢您的帮助。我想,我尝试了很多解决方案,但迷失了自己。果然,答案就在眼前。再次感谢您的帮助
标签: c# wpf multithreading user-interface backgroundworker