后台线程不会阻止进程的关闭
。当某个程序的所有前台线程完成后,进程就终止程序退出了,当然后台线程也会随即停止。在.NET中用Thread
创建的线程默认都是前台线程,用线程池、BeginXXX
等启用的线程都是后台线程
线程同步:即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又处于等待状态,实现线程同步的方法有很多,临界区对象就是其中一种。
同步就是协同步调,按预定的先后次序进行运行。如:你说完,我再说。
- 新建一个线程(无参数,无返回值)
Thread th = new Thread(new ThreadStart(PrintName));
public void PrintName() // 函数
{
//函数体
}
- 有参数时
Thread th = new Thread(new ParameterizedThreadStart(PrintName));
public void PrintName(string name) // 函数
{
//函数体
}
- 如果遇到又需要返回值,又需要参数的时候,就可以考虑用异步:
但是需要先申明个委托
public delegate string MethodCaller(string name);//定义个代理
MethodCaller mc = new MethodCaller(GetName);
string name = "my name";//输入参数
IAsyncResult result = mc.BeginInvoke(name,null, null);
string myname = mc.EndInvoke(result);//用于接收返回值
public string GetName(string name) // 函数
{
return name;
}
避免使用 BeginInvoke(在控件中使用)
private void ShowMessage(string message) { this.BeginInvoke(new MethodInvoker(delegate { txtSysMessage.Text += message +"-------"+DateTime.Now.ToString()+ "\r\n"; })); }
private void ShowMessage3(string message) { txtSysMessage.BeginInvoke((MethodInvoker)delegate { txtSysMessage.Text += message + "-------" + DateTime.Now.ToString() + "\r\n"; }); }
private void ShowMessage1(string message) { listBoxMessage.BeginInvoke((MethodInvoker)delegate { if (listBoxMessage.Items.Count > 200) { listBoxMessage.Items.RemoveAt(0); } listBoxMessage.Items.Add(message + "-------" + DateTime.Now.ToString()); }); }
public static void Dispatch(Action action) { if (DispatchObject == null || DispatchObject.CheckAccess()) { action(); } else { DispatchObject.Invoke(action); } }
this.validationErrorService.ErrorsChangedEvent += delegate(object sender, EventArgs args) { DispatcherService.Dispatch(() => { this.validationErrorsView.ErrorsDataGrid.ItemsSource = this.validationErrors; this.validationErrorsView.ErrorsDataGrid.Items.Refresh(); }); };
这种技术常用在2个或者多个线程需要独占访问某系资源的情况下
AutoResetEvent 允许线程通过发信号互相通信。通常,此通信涉及线程需要独占访问的资源。
线程通过调用 AutoResetEvent 上的 WaitOne 来等待信号。如果 AutoResetEvent 处于非终止状态,则该线程阻塞,并等待当前控制资源的线程
通过调用 Set 发出资源可用的信号。
可以通过将一个布尔值传递给构造函数来控制 AutoResetEvent 的初始状态,如果初始状态为
终止状态 true
非终止状态 false 如果 AutoResetEvent 处于非终止状态,则该线程阻塞,并等待当前控制资源的线程,通过调用 Set 发出资源可用的信号。
通俗的来讲只有等myResetEven.Set()成功运行后,myResetEven.WaitOne()才能够获得运行机会;Set是发信号,WaitOne是等待信号,只有发了信号,
等待的才会执行。如果不发的话,WaitOne后面的程序就永远不会执行。
初始化需要注意的是,一般初始化为“未信号”,也就是所谓的“Not signaled”。关于这一点,文档的解释是“可以通过将一个布尔值传递给构造函数来控制 AutoResetEvent 的初始状态,如果初始状态为终止状态,则为 true;否则为 false。”也就是说Not Signaled=非终止状态。一般情况下我看大多数程序都是初始化为“非终止状态”的。这里面的原因很显然:非终止状态可以等待一个信号来释放线程
相关参考:http://blog.csdn.net/jcx5083761/article/details/8552627
1,Delegate的代码
1 public delegate void myDelegate(string str); 2 public static void HellowChinese0(string strChinese) 3 { 4 Console.WriteLine("Good morning," + strChinese); 5 } 6 7 private static void demo0() 8 { 9 myDelegate d = new myDelegate(HellowChinese0); 10 d("demo0"); 11 }
2,Action:指定那些只有输入参数,没有返回值的委托
1 public static void HellowChinese(string strChinese) 2 { 3 Console.WriteLine("Good morning," + strChinese); 4 } 5 6 static void demo1() 7 { 8 Action<string> action = HellowChinese; 9 action("demo1"); 10 }
3,Func:有返回值!
1 public static string HelloEnglish(string strEnglish) 2 { 3 return "Good morning," + strEnglish; 4 } 5 static void demo2() 6 { 7 Func<string, string> f = HelloEnglish; 8 Console.WriteLine(f("demo2")); 9 }
Invoke,需要等待委托的方法执行返回后才执行下面的代码
begininvoke不需要
Invoke:同步,使用主线程
BeginInvoke:异步,另外起一个线程
sleep和wait都是使线程暂时停止执行的方法,但它们有很大的不同。
1. sleep是线程类Thread 的方法,它是使当前线程暂时睡眠,可以放在任何位置。而wait,它是使当前线程暂时放弃对象的使用权进行等待,必须放在同步方法或同步块里。
2.Sleep使用的时候,线程并不会放弃对象的使用权,即不会释放对象锁,所以在同步方法或同步块中使用sleep,一个线程访问时,其他的线程也是无法访问的。
而wait是会释放对象锁的,就是当前线程放弃对象的使用权,让其他的线程可以访问。
3.线程执行wait方法时,需要其他线程调用Monitor.Pulse()或者Monitor.PulseAll()进行唤醒或者说是通知等待的队列。
而sleep只是暂时休眠一定时间,时间到了之后,自动恢复运行,不需另外的线程唤醒.