.Net多线程

  关于多线程处理,根据自己的学习做了一下总结,算是复习用,下面主要贴一些实例Demo。看此博客建议先将.Net委托(拉姆达表达式)先学习一下,否则,看起来可能比较吃力,至少我是这样的。

 为了清晰,我把标题做了红字黄底加粗显示。

  1,启动线程调用无参无返回值的方法

Console.WriteLine("主线程开始");
Thread t1 = new Thread(new ThreadStart(Test1));
//可以通过IsBackground=true,把指定线程设置为后台线程。
//默认创建的进程都是“前台线程”,只有当所有“前台线程”都执行完毕后“进程”才会结束。
//后台线程在所有前台线程执行完毕后,自动退出。
t1.IsBackground = true;
t1.Start();
//在哪个线程中执行,就阻塞了哪个线程,那个线程要等待t1线程执行完毕后,然后才会继续。
//如果不理解,把t1.Join()注掉观察结果
//Join可以在在参数中设置阻塞时间,例如t1.Join(1000)
t1.Join();
Console.WriteLine("主线程结束");
Console.Read();

  2,启动线程调用有参数无返回值的方法

    ①利用预定义的函数调用

Console.WriteLine("主线程开始");
Thread t2 = new Thread(new ParameterizedThreadStart(Test2));
t2.Start(100);
Console.WriteLine("主线程结束");
Console.Read();

    ②将函数封装到类中,演变成调用无参数无返回值的方法

MyClass mc = new MyClass();
mc.Num = 100;
Thread t3 = new Thread(new ThreadStart(mc.Test3));
t3.Start();
Console.Read();

class MyClass

{

    private int num;

    public int Num

    {

        get { return num; }

        set { num = value; }

    }

 

    public void Test3()

    {

        int result = 0;

        for (int i = 0; i < this.Num; i++)

        {

            result += i;

        }

        Console.WriteLine(result);

    }

}

  3,启动线程调用有参数有返回值得方法

    ①BackgroundWorker实现

BackgroundWorker backWorker = new BackgroundWorker();
backWorker.DoWork += backWorker_DoWork;
backWorker.RunWorkerCompleted += backWorker_RunWorkerCompleted;
backWorker.RunWorkerAsync(new int[] { 100 });
Console.Read();

static void backWorker_DoWork(object sender, DoWorkEventArgs e)
{
    if (e.Argument != null)
    {
        int[] arr = e.Argument as int[];
        e.Result = Test4(arr[0]);
    }
}

private static void backWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    Console.WriteLine(e.Result);
}

    ②异步委托调用实现

      A,BeginInvoke&EndInvke的方式实现

Console.WriteLine("主线程开始");
MyDel md = new MyDel(Test4);
IAsyncResult asyResult = md.BeginInvoke(100, null, null);
for (int i = 0; i < 10; i++)
{
    Console.WriteLine("主线程进行中..." + i);
}
//调用EndInvoke会阻塞线程,等待异步委托执行完毕。
int sum = md.EndInvoke(asyResult);
Console.WriteLine(sum);
Console.WriteLine("主线程结束");
Console.Read();

      B,回调的方式实现

MyDel md = new MyDel(Test4);
IAsyncResult asyResult = md.BeginInvoke(100, CallBack, "Test");
Console.WriteLine("主线程继续");
Console.Read();

private static void CallBack(IAsyncResult res)
{
    Console.WriteLine("回调函数执行中");
    AsyncResult ar = res as AsyncResult;
    int sum = ((MyDel)ar.AsyncDelegate).EndInvoke(ar);
    Console.WriteLine("返回值是:"+sum);
}

  4,终止线程

if (t1 != null)
{
    t1.Abort();
}

  5,跨线程访问控件

////如果不关闭跨线程访问控件检查,会抛出异常
//Thread t2 = new Thread(new ThreadStart(() =>
//{
//    this.textBox1.Text = "Hi";
//}));
//t2.IsBackground = true;
//t2.Start();
Thread t1 = new Thread(new ThreadStart(() =>
{
    //利用控件的Invoke方法,将控件的操作放到创建空间的线程中进行
    this.textBox1.Invoke(new Action<string>(UpdateText), "hello");
}));
t1.IsBackground = true;
t1.Start();

  6,线程池

Console.WriteLine("Main thread ID:" + Thread.CurrentThread.ManagedThreadId);
ThreadPool.QueueUserWorkItem(new WaitCallback((obj) =>
{
    Console.WriteLine("Thread 1 ID:" + Thread.CurrentThread.ManagedThreadId);
    for (int i = 0; i < 10; i++)
    {
        Console.WriteLine(".");
        Thread.Sleep(500);
    }
}));
ThreadPool.QueueUserWorkItem(new WaitCallback((obj) =>
{
    Console.WriteLine("Thread 1 ID:" + Thread.CurrentThread.ManagedThreadId);
    for (int i = 0; i < 10; i++)
    {
        Console.WriteLine("*");
        Thread.Sleep(500);
    }
}));
ThreadPool.QueueUserWorkItem(new WaitCallback((obj) =>
{
    Console.WriteLine("Thread 1 ID:" + Thread.CurrentThread.ManagedThreadId);
    for (int i = 0; i < 10; i++)
    {
        Console.WriteLine("=");
        Thread.Sleep(500);
    }
}));
Console.WriteLine("主线程继续");
Console.Read();

  7,锁机制

static long max = 100000;
static long idx = 0;
static readonly object objSync = new object();
static void Main(string[] args)
{
    Thread t1 = new Thread(new ThreadStart(() =>
    {
        for (int i = 0; i < max; i++)
        {
            lock (objSync)
            {
                idx++;
            }
        }            
    }));
    t1.IsBackground = true;
    t1.Start();
    for (int i = 0; i < max; i++)
    {
        lock(objSync)
        {
            idx--;
        }
    }
    t1.Join();
    Console.WriteLine("最终idx="+idx);
    Console.Read();

  8,单线程造成界面假死多线程解决

Random rd = new Random();

////单线程,线程一直在做死循环,无法更新界面

//while (true)

//{

//    label1.Text = rd.Next(0, 10).ToString();

//    label2.Text = rd.Next(0, 10).ToString();

//    label3.Text = rd.Next(0, 10).ToString();

//    Thread.Sleep(300);

//}  

 

//开启一个线程专门处理界面显示

t1 = new Thread(new ThreadStart(() =>

{

    while (true)

    {

        label1.Text = rd.Next(0, 10).ToString();

        label2.Text = rd.Next(0, 10).ToString();

        label3.Text = rd.Next(0, 10).ToString();

        Thread.Sleep(300);

    }

}));

t1.IsBackground = true;

t1.Start();

原文地址:https://www.cnblogs.com/aaron-song/p/4358835.html