http://www.111cn.net/net/160/52542.htm
1.委托,扩展方法,UI跨线程
using System.Threading;
public static class Extensions
{
//控件扩展方法(用于跨线程操作),因为为了线程的安全,防止资源竞争出现死锁或不一致的状态,.NET是不允许进行跨线程访问窗体控件的。
public static void SafeCall(this Control ctrl, Action callback)
{
if (ctrl.InvokeRequired)
{
ctrl.Invoke(callback);
}
else
{
callback();
}
}
//带返回值
public static string SafeCall(this Control ctrl, Func<string> callback)
{
if (ctrl.InvokeRequired)
{
return (string )( ctrl.Invoke(callback) );//同步
}
else
{
return (string )( callback() );
}
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
CheckForIllegalCrossThreadCalls = false;//方法二(禁用异常,不检查跨线程调用的安全问题,可以自由拖动窗体,不过在严格条件下也不可取,数据可能不一致)
//方法三(推荐使用)
//把你要保护起来的代码作为一个回调,然后任何需要保护一些代码的地方都可以这样调用
ThreadPool.QueueUserWorkItem(h =>
{
int i = 0;
while (true)
{
//如果没有SafeCall方法,将出现“线程间操作无效: 从不是创建控件“textBox1”的线程访问它。”的错误
匿名委托
//textBox1.SafeCall(delegate()
//{
// textBox1.Text = (i++).ToString();
//});
//Lambda表达式
textBox1.SafeCall(() =>
{
textBox1.Text = (i++).ToString();
});
//Thread.Sleep(100);
}
});
}
//抽奖示例
public bool flag = true;
public void choujiang()
{
flag = true;
while (flag)
{
Random rnd = new Random();
textBox1.Text = rnd.Next(1, 100).ToString();
//Application.DoEvents();//方法一:这样也可以防止UI界面线程的阻塞,不至于被卡死。但是在拖动界面或其他操作的时候,程序会被暂停
}
}
//开始
private void button1_Click(object sender, EventArgs e)
{
//choujiang();//方法一
new Action(choujiang).BeginInvoke(null, null);//方法二
}
//暂停
private void button2_Click(object sender, EventArgs e)
{
flag = false;
}
}
2.异步委托
delegate double weituo(double d);
static weituo w = new weituo(perimeter);
/// <summary>
/// 计算周长
/// </summary>
/// <param name="d"></param>
public static double perimeter(double d)
{
return d * Math.PI;
}
/// <summary>
/// 异步完成后回调的方法
/// </summary>
/// <param name="result"></param>
public static void method(IAsyncResult result)
{
Console.Write("hi~");
Console.WriteLine(w.EndInvoke(result));
}
static void Main(string[] args)
{
//开始异步执行
w.BeginInvoke(10, new AsyncCallback(method), null);
w.BeginInvoke(20, new AsyncCallback(method), null);
Console.Read();
}
3.线程池+委托
/// <summary>
/// 静态方法不需要实例化
/// </summary>
/// <param name="d"></param>
public static void perimeter(object d)
{
Console.WriteLine(Math.PI * (double)d);
Thread.Sleep(1000);
}
static void Main(string[] args)
{
int i = 1;
WaitCallback wcb = new WaitCallback(perimeter);
while (i < 15)
{
//将任务排入队列以便执行,您的回调方法将在某个线程池线程可用时执行
ThreadPool.QueueUserWorkItem(wcb, (double)i);
++i;
}
Console.Read();
}
===========================================================================================================================================
在多线程的情况下为了整个程序退出调用 System.Environment.Exit(System.Environment.ExitCode);
thread.Abort()很多时候不管用,它只是建议线程结束。