欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#线程处理

程序员文章站 2022-09-30 21:07:07
  C 支持通过多线程并行地执行代码,一个线程有它独立的执行路径,能够与其它的线程同时地运行。一个C 程序开始于一个单线程,这个单线程是被CLR和操作系统(也称为“主线程”)自动创建的,并具有多线程创建额外的线程。   除非被指定,否则所有的例子都假定以下命名 ......

  c#支持通过多线程并行地执行代码,一个线程有它独立的执行路径,能够与其它的线程同时地运行。一个c#程序开始于一个单线程,这个单线程是被clr和操作系统(也称为“主线程”)自动创建的,并具有多线程创建额外的线程。
  除非被指定,否则所有的例子都假定以下命名空间被引用了:

using system;
using system.threading;

c#开启线程的方法有:

  • 异步委托
  • 通过thread类
  • 线程池
  • 任务

  总的来说其实线程的开启基本都涉及到委托的使用。

一、异步委托开启线程

首先来看一个比较简单的例子,采用第一种开启线程的方法——异步委托

using system;
using system.threading;

namespace study
{
    class program
    {
        static void test()
        {
            console.writeline("testthread");
        }
        static void main(string[] args)
        {
            action a = test;
            a.begininvoke(null, null);
            console.writeline("mainthread");
            console.readline();
        }
    }
}

  编译运行,发现结果与预期有所不同。结果如下图
C#线程处理
  如果按着逐行运行代码的方式,那么应该是先输出testthread,但是结果却是先输出mainthread。
  将a.begininvoke(null,null);console.writeline("mainthread");对调位置之后,结果和之前的依然一致。这就说明,异步委托开启的线程是和主线程同时同步进行的。
  action委托是指向一个没有返回值的函数,那么假设一个线程,我们需要取得他的返回结果并输出,那么就要用到func委托。
  看下面的源码

using system;
using system.threading;

namespace summerstudy
{
    class program
    {
        static string test(int i, string str)
        {
            console.writeline("testthread" + "\t参数i是:" + i);
            return str;
        }
        static void main(string[] args)
        {
            func<int, string, string> a = test;
            iasyncresult res = a.begininvoke(1, "返回值", null, null);
            string o = a.endinvoke(res);
            console.writeline("mainthread\t" + "线程返回值是:" + o);
            console.readline();
        }
}

C#线程处理
同时异步委托开启线程中,判断线程是否结束的方法也有两种,一种是利用iasyncresult的iscompleted方法,一种是使用方法进行线程结束判断。
  具体使用方法如下。

  1. iscompleted(bool)
iasyncresult ia = a.begininvoke()
if(ia.iscompleted == false)
{
    //goon
}
  1. asyncwaithandle
iasyncresult ia = a.begininvoke()
ia.asyncwaithandle.waitone(time);//time为等待时间,超时后才会运行下一行代码,未完成直接跳出返回false

  或者通过自定义方法,begininvoke中倒数第二个参数是一个委托,传递一个函数,在线程结束之后会自动的调用。

static string test(int a)
{

}
func<int, string> a = test;
iasyncresult ia = a.begininvoke(100, callback, a);
static void callback(iasyncresult ar)
{
    func<int, string> a = ia.asyncstate as func<int, string>;
    string res = a.endinvoke(ar);
}

  在使用lambda表达式作为委托的时候,最后一个参数可以为空,因为lambda表达式可以访问外部变量。

二、使用thread类开启线程

  使用thread类创建一个实例,它的构造方法中需要传递一个委托。通过委托绑定线程。
  直接上代码

using system;
using system.threading;

namespace study
{
    class program
    {
        static void test()
        {
            console.writeline("thread");
            thread.sleep(2000);
            console.writeline("timeover");
        }
        static void main(string[] args)
        {
            thread t = new thread(test);
            t.start();
            console.writeline("main");
            console.read();
        }
    }
}

C#线程处理
  对于需要传递参数的委托,则必须制定参数类型为object,在线程start方法中传递参数

namespace summerstudy
{
    class program
    {
        static void test(object c)
        {
            int id = thread.currentthread.managedthreadid;
            console.writeline("thread,\t线程id为" + id + ",\t参数是:" + c);
            thread.sleep(2000);
            console.writeline("timeover");

        }
        static void main(string[] args)
        {
            thread t = new thread(test);
            t.start("xxx.avi");
            console.writeline("main");
            console.read();
        }
    }
}

C#线程处理
  当然你也可以自定义一个类,在类中自定义数据传递。

三、线程池

  这种方法有助于节省时间,具体使用方法如下

using system;
using system.threading;

namespace summerstudy
{
    class program
    {
        static void test(object c)
        {
            int id = thread.currentthread.managedthreadid;
            console.writeline("thread,\t线程id为" + id + ",\t参数是:" + c);
            thread.sleep(2000);
            console.writeline("timeover");

        }
        static void main(string[] args)
        {
            threadpool.queueuserworkitem(test, "asfasf");
            console.read();
        }
    }
}

  其中委托必须要有一个参数,无论是否使用该参数。且只适用于使用时间短的线程,不能改变优先级

四、任务

  使用task类开启线程,还有taskfactory创建
  task类实例

using system;
using system.threading;
using system.threading.tasks;

namespace summerstudy
{
    class program
    {
        static void test(object c)
        {
            int id = thread.currentthread.managedthreadid;
            console.writeline("thread,\t线程id为" + id);
            thread.sleep(2000);
            console.writeline("timeover");

        }
        static void main(string[] args)
        {
            task t = new task(test, "asfgasg");
            t.start();

            //或者

            taskfactory tf = new taskfactory();

            task t1 = tf.startnew(test);
            console.read();
        }
    }
}

我的掘金:warrenryan

我的简书:warrenryan

欢迎关注我的博客获得第一时间更新

我的github:warrenryan

我的博客园:warrenryan