【问题标题】:C# - Delegates and BackgroundWorkersC# - 代表和BackgroundWorkers
【发布时间】:2017-06-08 08:44:51
【问题描述】:

我是 C# 和面向对象编程的新手。我有一个解析文本文件的应用程序。

默认情况下,程序在主线程上执行,因此应用程序会冻结直到执行。

我有 5 个 void 方法,它们将 string 列表作为参数。

根据各种 CheckBox 选项,这 5 个 void 方法组合执行。

BackgroundWorker 在不同的线程上执行操作。因此,应用程序不会冻结。

但是,对于每个组合,我需要 15+ BackgroundWorkers

以下是我的代码:

public partial class Form1 : Form
{
    List<string> textFiles = new List<string>();

    public Form1()
    {
        InitializeComponent();
    }

    public void mParsing(List<string> textFiles) { /* parsing logic */ }
    public void iParsing(List<string> textFiles) { /* parsing logic */ }
    public void aParsing(List<string> textFiles) { /* parsing logic */ }
    public void qParsing(List<string> textFiles) { /* parsing logic */ }

    public void Summary()
    {
        // Logic to generate summary   
    }

    private void btnGo_Click(object sender, EventArgs e)
    {
        if (checkM.Checked == true && checkI.Checked == false && checkA.Checked == false && checkQ.Checked == false)
        {
            backgroundWorker1.RunWorkerAsync();
        }
        else if (checkM.Checked == true && checkI.Checked == true && checkA.Checked == false && checkQ.Checked == false)
        {
            backgroundWorker2.RunWorkerAsync();
        }            

        //So On....
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        mParsing(textFiles);
        Summary();
    }
    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        DialogResult dialogResult = MessageBox.Show("View Summary?", MessageBoxButtons.YesNo);
        if (dialogResult == DialogResult.Yes)
        {
            string summary = filepath;
            Process.Start("notepad.exe", summary);
        } 
    }
    private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
    {
        mParsing(textFiles);
        iParsing(textFiles);
        Summary();
    }
    private void backgroundWorker2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        DialogResult dialogResult = MessageBox.Show("View Summary?", MessageBoxButtons.YesNo);
        if (dialogResult == DialogResult.Yes)
        {
            string summary = filepath;
            Process.Start("notepad.exe", summary);
        }
    }
}

Func&lt;&gt; 不接受 void 数据类型,我很难理解委托和多线程。

我的问题是,我不知道如何避免多个后台工作人员。这可以在代表的帮助下实现吗?

更新: .NET Framework 版本:4.0

【问题讨论】:

  • 您是否使用 backgroundworker 只是因为这是您发现执行多线程的第一种方法并且您坚持使用它?还是出于某种特定原因?我问是因为它处理线程的方式有点过时。正如您所发现的那样,它过于复杂。
  • @Jamiec,我使用了后台工作程序,因为我过去曾在 VB.NET 应用程序中使用过它。上述方法需要按顺序运行。如何实现?此外,我们将不胜感激。
  • RunWorkerAsync() 允许您将参数传递给 DoWork。很明显,你会在这里很好地使用它,一个 BGW 就足够了。
  • @Hans 但我需要将多个方法传递给 DoWork。它不允许我通过 backgroundWorker1.RunWorkerAsync(mParsing(textFiles), Summary());
  • 它允许你传递 any 对象。只需创建您自己的小类,它可以包含您需要的任意数量的字段。您将调用的方法应该在 DoWork 代码中。但是,如果出于某种原因方便的话,您可以将该类的一个字段声明为委托。

标签: c# multithreading methods delegates backgroundworker


【解决方案1】:

在 C# 中,async/await 正是您所需要的。 举个例子:

private async void btnGo_Click(object sender, EventArgs e)
{
    if (checkM.Checked == true && checkI.Checked == false && checkA.Checked == false && checkQ.Checked == false)
    {
        await mParsing(textFiles);
        DialogResult dialogResult = MessageBox.Show("View Summary?", MessageBoxButtons.YesNo);
        if (dialogResult == DialogResult.Yes)
        {
            string summary = filepath;
            Process.Start("notepad.exe", summary);
        } 
    }
}

要使这两个函数都起作用,btnGo_ClickmParsing 必须在其定义中包含关键字 async。另外解析函数的返回类型必须改为Task。

public async Task mParsing(List<string> textFiles)
{
    //Method containing parsing logic
}

此外,您需要对(现在是异步的)mParsing 函数进行一些更改。 例如。像new WebClient().DownloadString(url) 这样的阻塞调用必须替换为非阻塞调用new WebClient().DownloadStringTaskAsync(url)

由于并非总是有可用的非阻塞调用,您也可以使用Task.Run()

public async Task mParsing(List<string> textFiles)
{
    await Task.Run(() => {
        //Do blocking calls
    });
}

【讨论】:

  • 您好 Coolerfarmer,不幸的是,我使用的是 .NET Framework 4。我无法将其更改为最新版本。没有异步如何实现?
【解决方案2】:

Coolerfarmer 的回答适用于 .NET 4.5。

但是,由于 .NET 4.0 的限制,在线程和委托的帮助下设法实现异步执行

这可能不是执行方法组合执行的有效方式。

我所做的是,创建了一个具有执行顺序的单独方法并使用了以下代码:

 public partial class Form1 : Form
{
    List<string> textFiles = new List<string>();

    public Form1()
    {
        InitializeComponent();
    }

    public void mParsing(List<string> textFiles) { /* parsing logic */ }
    public void iParsing(List<string> textFiles) { /* parsing logic */ }
    public void aParsing(List<string> textFiles) { /* parsing logic */ }
    public void qParsing(List<string> textFiles) { /* parsing logic */ }

    public void Summary()
    {
        // Logic to generate summary   
    }

    private void btnGo_Click(object sender, EventArgs e)
    {
        if (checkM.Checked == true && checkI.Checked == false && checkA.Checked == false && checkQ.Checked == false)
        {
            Thread worker = new Thread(mOption);
                if (!worker.IsAlive)
                {

                    worker.Start();
                    frm.Show(); // Displaying Form - Performing Operation.. Please Wait... 
                    btn1.Enabled = false;
                }
        }
        else if (checkM.Checked == true && checkI.Checked == true && checkA.Checked == false && checkQ.Checked == false)
        {
            Thread worker = new Thread(miOption);
                if (!worker.IsAlive)
                {

                    worker.Start();
                    frm.Show(); // Displaying Form - Performing Operation.. Please Wait... 
                    btn1.Enabled = false;
                }
        }            

        //So On....
    }


        private void mOption()
        {
            mParsing(textFiles);
            Summary();

            MethodInvoker inv = delegate
            {
                frm.Hide();

        DialogResult dialogResult = MessageBox.Show("View Summary?", MessageBoxButtons.YesNo);
        if (dialogResult == DialogResult.Yes)
        {
            string summary = filepath;
            Process.Start("notepad.exe", summary);
        } 
                this.btn1.Enabled = true;

            };
            this.Invoke(inv);
        }

        private void miOption()
        {
            mParsing(textFiles);
            iParsing(textFiles);
            Summary();

            MethodInvoker inv = delegate
            {
                frm.Hide();

        DialogResult dialogResult = MessageBox.Show("View Summary?", MessageBoxButtons.YesNo);
        if (dialogResult == DialogResult.Yes)
        {
            string summary = filepath;
            Process.Start("notepad.exe", summary);
        } 
                this.btn1.Enabled = true;

            };
            this.Invoke(inv);
        }

}

欢迎任何带有解释的输入,感谢大家的输入和建议。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多