C# 在openfiledialog列表中使用后台工作程序

C# 在openfiledialog列表中使用后台工作程序,c#,C#,我尝试在我的应用程序中,通过.txt文件加载URL列表,将.txt文件的每一行传递给backgroundworker进行处理,中断线程以更新UI,我得到错误: '此BackgroundWorker当前正忙,无法同时运行多个任务。' 代码: 私有无效BTNIMPortURL\u单击对象发送者,事件参数e { OpenFileDialog ofd=新建OpenFileDialog { InitialDirectory=@C:\, Title=选择URL文件。。。, DefaultExt=txt, F

我尝试在我的应用程序中,通过.txt文件加载URL列表,将.txt文件的每一行传递给backgroundworker进行处理,中断线程以更新UI,我得到错误:

'此BackgroundWorker当前正忙,无法同时运行多个任务。'

代码:

私有无效BTNIMPortURL\u单击对象发送者,事件参数e { OpenFileDialog ofd=新建OpenFileDialog { InitialDirectory=@C:\, Title=选择URL文件。。。, DefaultExt=txt, Filter=txt文件*.txt |*.txt, FilterIndex=2, }; 如果ofd.ShowDialog==DialogResult.OK { 使用StreamReader file=new StreamReaderofd.FileName { 如果bgWorker.IsBusy!=真 { var line=string.Empty; 而line=file.ReadLine!=null { bgWorker.RunWorkerAsyncline.ToString; } } 其他的 { } } } } public void bgWorker\u RunWorkerCompletedobject发送方,RunWorkerCompletedEventArgs e { 如果e.错误!=null Helpers.ReturnMessagestring.FormatThread错误:{0},e.错误; 否则,如果e.取消 Helpers.returnmessage进程已取消。; 其他的 Helpers.returnMessageURL已成功导入。; } 私有无效BgWorker\u工作对象发送方,System.ComponentModel.DoWorkEventTargets e { var input_url=e.参数为字符串; var platform=string.Empty; Invokenew MethodInvoker=>{platform=comboBoxSelectMassMacroTemplate.Text;}; 如果平台==平台-[buddypress].txt { Invokenew MethodInvoker=> { 字符串root\u domain=Helpers.GetRootUrlinput\u url; 如果!文件。Exists@Macros\MassMacros\+根目录域+.txt { 文件WriteAllText@Macros\+Helpers.GetRootUrlinput_url+.txt,txtBoxPlatformMassMacro.Text.Replace%DOMAIN%,Helpers.GetRootUrlinput_url; txtBoxMassMacroOutput.AppendText$[{DateTime.Now}]-+Helpers.GetBuddyPressFlagsinput\u url+-+Helpers.GetRootUrlinput\u url; txtBoxMassMacroOutput.AppendTextEnvironment.NewLine; } }; } }
我知道查看代码是因为每次读取代码时我都要传递要处理的行,这是正确的方法吗?我觉得我有一些不应该的代码,比如,我应该在backgroundworker中也有while循环吗?我对backgroundworkers有点不在行,非常感谢您的帮助。

您会遇到错误,因为RunWorkerAsync调用是异步的,您没有等待它完成:

while ((line = file.ReadLine()) != null)
{
    bgWorker.RunWorkerAsync(line.ToString());
}
在处理新URL之前,您需要显式地告诉循环等待worker完成。这样的东西在未经测试的情况下可能会起作用:

while ((line = file.ReadLine()) != null)
{
    bgWorker.RunWorkerAsync(line.ToString());
    //Keep looping til the worker is finished.
    while(bgWorker.IsBusy) 
        Thread.Sleep(10);
}
正如其他人所说,我个人会使用async/await模式来完成您想要的。类似的方法可能会再次奏效,我还没有测试过:

private async void BtnImportURLs_Click(object sender, EventArgs e)
{
    OpenFileDialog ofd = new OpenFileDialog
    {
        InitialDirectory = @"C:\",
        Title = "Select URLs file ...",
        DefaultExt = "txt",
        Filter = "txt files (*.txt)|*.txt",
        FilterIndex = 2,
    };

    if (ofd.ShowDialog() == DialogResult.OK)
    {
        foreach(string s in File.ReadLines(ofd.FileName))
        {
            await ProcessUrl(s, comboBoxSelectMassMacroTemplate.Text);
        }
    }
}

private async Task ProcessUrl(string Url, string SelectedMassMacroTemplate)
{
    var input_url = Url;
    var platform = SelectedMassMacroTemplate;

    if (platform == "platform-[buddypress].txt")
    {
        string root_domain = Helpers.GetRootUrl(input_url);
        if (!File.Exists(@"Macros\MassMacros\" + root_domain + ".txt"))
        {
            await File.WriteAllTextAsync(@"Macros\" + Helpers.GetRootUrl(input_url) + ".txt", txtBoxPlatformMassMacro.Text.Replace("%DOMAIN%", Helpers.GetRootUrl(input_url)));
            txtBoxMassMacroOutput.AppendText($"[{DateTime.Now}] - " + Helpers.GetBuddyPressFlags(input_url) + " - " + Helpers.GetRootUrl(input_url));
            txtBoxMassMacroOutput.AppendText(Environment.NewLine);
        }
    }
}
使用async/await,只要代码不在单独的线程中运行,就不需要调用来更新UI


编辑:File.WriteAllTextAsync方法似乎仅在.Net标准2.1预览版中可用。您可能需要,或者使用Task在单独的线程中运行写入操作。run可能效率较低。

只需将文件名传递给BackgroundWorker.DoWork,并让它在文件上打开和循环为什么不使用异步任务并等待结果,我上个月开始使用它,我对此印象深刻。搜索异步任务处理和等待,我相信它会解决你的问题。谢谢史蒂夫,我从没想过,@Sayed这是我名单上的下一个问题:我听说异步比BG好得多。谢谢你。哇,谢谢你,帕特里克,这是一个更好的方法,我将来会学习使用异步/等待。