在具有委托使用的多线程winform应用程序中,什么被认为是良好的编程实践
本文关键字:什么 认为是 编程 应用程序 winform 多线程 | 更新日期: 2023-09-27 17:57:52
我正在修改一个用C#编写的应用程序,该应用程序大量使用多线程来向用户播放音频文件和显示图像。考虑到它是多线程的,我需要经常使用Invoke方法来更改表单元素。我遇到了一种我不太适应的模式,我发现自己经常写一些小的委托方法,通常只做一件事。一个例子如下:
delegate void setImageCallback(Image img);
private void setImage(Image img)
{
this.pictureBox1.Image = img;
}
private void someOtherMethod()
{
...
if (this.pictureBox1.InvokeRequired)
{
this.Invoke(new setImageCallback(setImage), Image.FromFile("example.png");
}
else
{
this.pictureBox1.Image = Image.FromFile("example.png");
}
...
}
人们通常是如何处理这些情况的,这样你就不会发现自己为了保持线程安全而写了大量的委托和方法?显然,类似方法的合并是很好的,但如果我可能需要更新表单上的每个表单元素,我不想为每个方法都有一个"修改"委托和方法。
谢谢。
这里有一个很好的例子。
this.BeginInvoke( (Action) (()=>
{
pictureBox1.Image = Image.FromFile("example.png");
}));
您绝对不需要为每一个单独的委托。您可以使用Action
委托和lambda表达式来简化它,如下所示:
private void SomeOtherMethod()
{
Action action = () => pictureBox1.Image = Image.FromFile("example.png");
if (pictureBox1.InvokeRequired)
{
Invoke(action);
}
else
{
action();
}
}
或者,您可以将if
语句和InvokeRequired
检查分离出来,并对其进行进一步的推广,如下所示:
public static void InvokeIfRequired(Control control, Action action)
{
if (control.InvokeRequired)
{
control.Invoke(action);
}
else
{
action();
}
}
private void SomeOtherMethod()
{
InvokeIfRequired(() => pictureBox1.Image = Image.FromFile("example.png");
}
我会将MethodInvoker
类型与匿名方法或lambda表达式结合使用。我还将调用逻辑构建到方法本身中,而不是使用单独的线程安全方法:
void SomeMethod(/* with whatever args */) {
if (InvokeRequired)
Invoke(new MethodInvoker(() => SomeMethod(/* args used to call method */)));
else
// the method body itself
}