C# - 委托和 BackgroundWorkers

C# - Delegates and BackgroundWorkers

我是 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<> 不接受 void 数据类型,我很难理解委托和多线程。

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

更新: .NET Framework 版本:4.0

在 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。另外解析函数的return类型必须改为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 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);
        }

}

欢迎任何有解释的意见,感谢大家的意见和建议。