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_Click
和 mParsing
必须在其定义中包含关键字 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);
}
}
欢迎任何有解释的意见,感谢大家的意见和建议。
我是 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_Click
和 mParsing
必须在其定义中包含关键字 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);
}
}
欢迎任何有解释的意见,感谢大家的意见和建议。