ryb*_*ome 5 c# multithreading delegates event-handling winforms
我正在修改一个用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");
}
...
}
Run Code Online (Sandbox Code Playgroud)
人们通常如何处理这些情况,以便您不会发现自己编写一些荒谬的代表和方法只是为了保持线程安全?显然,类似方法的合并很好,但如果我可能需要更新表单上的每个表单元素,我不希望为每个表单元素和方法都有一个"修改"委托和方法.
谢谢.
一个很好的例子是在这里.
this.BeginInvoke( (Action) (()=>
{
pictureBox1.Image = Image.FromFile("example.png");
}));
Run Code Online (Sandbox Code Playgroud)
你绝对不需要为每个委托单独委托.您可以使用Action委托和lambda表达式来简化它,如下所示:
private void SomeOtherMethod()
{
Action action = () => pictureBox1.Image = Image.FromFile("example.png");
if (pictureBox1.InvokeRequired)
{
Invoke(action);
}
else
{
action();
}
}
Run Code Online (Sandbox Code Playgroud)
或者您可以将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");
}
Run Code Online (Sandbox Code Playgroud)