在C#中处理线程状态的模式 [英] Pattern to handle threads status in C#
问题描述
命名空间ThreadTest
{
public partial class Form1:Form
{
//该委托启用异步调用来设置
// TextBox控件上的text属性。
delegate void ChangedCallback(object sender,JobEventArgs e);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender,EventArgs e)
{
MyThread myThread = new MyThread();
myThread.Changed + = new MyThread.JobEventHandler(myThread_Changed);
//创建线程对象,通过ThreadStart代理传递Alpha.Beta方法
//。这不会启动线程。
线程oThread = new Thread(new ThreadStart(myThread.MyJob));
//启动线程
oThread.Start();
}
void myThread_Changed(object sender,JobEventArgs e)
{
// InvokeRequired需要将
//调用线程的线程ID与创建线程的线程ID。
//如果这些线程不同,它返回true。
if(this.textBox1.InvokeRequired)
{
ChangedCallback d = new ChangedCallback(myThread_Changed);
this.Invoke(d,new object [] {sender,e});
}
else
{
//显示我的线程状态
textBox1.Text + = e.Counter;
}
}
}
public class MyThread
{
//挂接更改通知的委托类型。
public delegate void JobEventHandler(object sender,JobEventArgs e);
//当列表的
//元素更改时,客户端可以使用该事件进行通知。
公共事件JobEventHandler已更改;
//调用已更改事件;每当列表更改时调用
protected virtual void OnChanged(JobEventArgs e)
{
if(Changed!= null)
更改(this,e);
}
public void MyJob()
{
for(int i = 0; i <1000; i ++)
{
Thread.sleep代码(1000);
JobEventArgs e = new JobEventArgs(i);
OnChanged(e);
}
}
}
public class JobEventArgs
{
public int Counter {get;组; }
public JobEventArgs(int i)
{
Counter = i;
}
}
}
对我来说看起来不错实际上,您使用观察者模式 。这只是c#的很好的事件语法,消除了界面并减少了样板。
但是,有很多冗余代码和其他可读性问题。
$ b
- 当指定memeber(例如
this.textBox1 c
)时, / code>或
this.Invoke(...)
。 - 尽量总是指定可见性,例如
private
或public
用于方法。 - 组启用简写语法。例如:
new Thread(myThread.MyJob)
或myThread.Changed + = myThread_Changed
。 - 考虑使用简单的Action作为事件处理程序委托类型而不是自定义(
ChangedCallback
)。然后,myThread_Changed方法可以接受int作为单个参数,允许您删除大量的冗余类型。 - 为了避免在检查null和调用之前发生事件的线程本地副本
像这样:
JobEventHandler tmp =更改;
if(tmp!= null)tmp(this,e);
I am currently developing a program that must handle multiple threads. When I start the program I run multiple threads (my example is limited to one). I have to display their status in a single TextBox. I opted for the next solution. Is this way is correct? Are there any other pattern? The Observer perhaps? I can't find a good way to do this on the web.
namespace ThreadTest
{
public partial class Form1 : Form
{
// This delegate enables asynchronous calls for setting
// the text property on a TextBox control.
delegate void ChangedCallback(object sender, JobEventArgs e);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
MyThread myThread = new MyThread();
myThread.Changed += new MyThread.JobEventHandler(myThread_Changed);
// Create the thread object, passing in the Alpha.Beta method
// via a ThreadStart delegate. This does not start the thread.
Thread oThread = new Thread(new ThreadStart(myThread.MyJob));
// Start the thread
oThread.Start();
}
void myThread_Changed(object sender, JobEventArgs e)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.textBox1.InvokeRequired)
{
ChangedCallback d = new ChangedCallback(myThread_Changed);
this.Invoke(d, new object[] { sender, e });
}
else
{
// Display the status of my thread
textBox1.Text += e.Counter;
}
}
}
public class MyThread
{
// A delegate type for hooking up change notifications.
public delegate void JobEventHandler(object sender, JobEventArgs e);
// An event that clients can use to be notified whenever the
// elements of the list change.
public event JobEventHandler Changed;
// Invoke the Changed event; called whenever list changes
protected virtual void OnChanged(JobEventArgs e)
{
if (Changed != null)
Changed(this, e);
}
public void MyJob()
{
for (int i = 0; i < 1000; i++)
{
Thread.Sleep(1000);
JobEventArgs e = new JobEventArgs(i);
OnChanged(e);
}
}
}
public class JobEventArgs
{
public int Counter { get; set; }
public JobEventArgs(int i)
{
Counter = i;
}
}
}
It looks just fine to me. In fact you are using the observer pattern. It's just c#'s nice event syntax eliminating the interface and reducing boilerplate.
However, there is a lot of redundant code and other readability problems in there.
- The
this
qualifier is redundant when specifying a memeber such asthis.textBox1
orthis.Invoke(...)
. - Try to always specify visibility such as
private
orpublic
for methods. - A suitable delegate is created automatically around a method-group enabling a shorthand syntax. For example:
new Thread(myThread.MyJob)
ormyThread.Changed += myThread_Changed
. - Consider using simple Action as event handler delegate types instead of a custom (
ChangedCallback
). The myThread_Changed method can then just accept an int as single parameter allowing you to drop lots of redundant types. - To avoid problems make a thread-local copy of the event before checking for null and invoking.
Like this:
JobEventHandler tmp = Changed;
if (tmp != null) tmp(this, e);
这篇关于在C#中处理线程状态的模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!