关于Thread的那些事

1 : 你能够调用线程的实例方法Join来等待一个线程的结束.比如:

public static void MainThread()
{
Thread t = new Thread(Go);
t.Start();
t.Join();
Console.WriteLine("Thread t has ended!");
} static void Go()
{
for (int i = 0; i < 1000; i++)
Console.Write("y");
}

分析:在打印了1000个Y之后,后面就会输出”Thread has ended!”.

你能够在调用Join方法的时候给它一个timeout的參数,比如要超过1秒.

   t.Join(1000);
t.Join(TimeSpan.FromSeconds(1));

2 : 为线程传递參数

为线程传递參数的最简单的方法莫过于运行一个lambda表达式,然后在方法里面给參数了,比如:

        static void Main(string[] args)
{
Thread t = new Thread(()=>Print("hello ,world !"));
t.Start();
Console.ReadKey();
}
static void Print(string message)
{
Console.WriteLine(message);
}

使用这样的方法,你能够传递不论什么參数.

当然Thread的构造函数中有一个传递參数的版本号,你也能够使用以下的代码来传递參数:

 static void Main()
{
Thread t = new Thread(Print);
t.Start("Hello from t!");
} static void Print(object messageObj)
{
string message = (string)messageObj;
Console.WriteLine(message);
}

分析:这里有一点须要注意,由于Print的方法签名必须匹配ParameterrizedThreadStart托付,所以Print的參数必须也是object,所以在Print方法中必须进行强制转换.

3: Lambda和捕获的变量

考虑以下的代码

            for (int i = 0; i < 10; i++)
{
new Thread(() => Console.Write(i)).Start();
}

分析:实际的输出是不确定的,你能够自己试试.

Why?

关键问题是局部变量i在for循环中指向的是相同的内存地址.因此,每一次都在一个执行时会被改变值的变量(i)上调用CW方法,在foreach中也存在相同问题.

解决问题的方法非常easy,比如使用一个暂时变量:

            for (int i = 0; i < 10; i++)
{
int temp = i;
new Thread(() => Console.Write(temp)).Start();
}

由于i是值变量,所以int temp=i会复制i的值给temp,而在for循环中temp变量都是不同的,所以能够解决问题.

以下的也是相同的道理:

            for (int i = 0; i < 10; i++)
{
new Thread((obj) => Console.Write(obj)).Start(i); //由于每个线程的obj都是不同的。
}

以下的案例可能更加明显一点:

            string text = "t1";
Thread t1 = new Thread(() => Console.WriteLine(text));
text = "t2";
Thread t2 = new Thread(() => Console.WriteLine(text)); t1.Start();
t2.Start();

无论你运行几次,貌似都是输出两次t2,为啥呢?

由于两个lambda表达式捕获的是同样的test变量,所以”t2”会被连续打印两次.

4.命名线程

给每个线程一个合适的名字对于调试来说非常有利,尤其是在VS中,由于县城窗体和调试位置工具栏中都会显示线程的名字.

可是你仅仅能设置一次线程的名字,尝试在以后更改名字会抛出一个异常,为变量命名的使用的是Name属性,比如:

            Thread worker = new Thread(Go);
worker.Name = "worker";
worker.Name = "worker";//会抛出异常

5.前台线程和后台线程

默认你显示创建的线程都是前台线程.

仅仅要前台线程有一个还在执行,应用程序就不会结束.

仅仅有全部的前台线程都结束了,应用程序才会结束.

在应用程序结束的时候,全部后台线程都会被终止.

你能够通过现成的IsBackground属性莱产讯和更改现成的状态.

案例:

            if (args.Length>0)
{
worker.IsBackground = true;
}
worker.Start();

假设args.Length>0,则worker就是后台线程,那么应用程序会马上终止.

否则worker默认就是前台线程,所以仅仅有在CR()方法结束后,应用程序才会终止.

所以当你有时候发现关闭了应用程序窗体,可是在任务管理器中应用程序仍然在执行,非常有可能是另一些前台线程在执行.

6.线程的优先级

enum ThreadPriority
{
Lowest,
BelowNormal,
Normal,
AboveNormal,
Highest
}

仅仅有在多个线程的环境中,线程优先级才实用.

把一个现成的优先级提高并不会提高实时系统的性能,由于进程的优先级才是应用程序的瓶颈.为了更好的实时工作,你必须提高进程的优先级.

比如:

process.PriorityClass=ProcessPriorityClass.High.

7.异常捕获

尝试在一个线程中捕获还有一个线程的异常是失败的.案例:

public static void Main()
{
try
{
new Thread(Go).Start();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message); //永远执行不到这里.
}
} static void Go() { throw null;}

我们再还有一个线程中抛出了异常(throw null),然后尝试在主线程中捕获它,我们永远都不会捕获到这个异常.

为了在还有一个线程中捕获异常,必须在那个线程上try,catch,finally.

所以我们能够这么做:

public static void Main()
{
new Thread(Go).Start();
} static void Go()
{
try
{
throw null;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}

8.全局捕获异常

Application.DispatcherUnhandledException 事件和Application.ThreadException 事件都仅仅有在主UI线程中抛出异常的时候才会被触发。

为了捕获全部的未处理的异常,你能够使用AppDomain.CurrentDomain.UnhandledException,尽管这个事件在不论什么未处理异常抛出的时候都会被触发。可是它不能让你阻止应用程序的关闭。

关于Thread的那些事的更多相关文章

  1. 说说Thread.Sleep(0)的那些奇怪的事

    写在前面 最近在弄一个传输组件,用到很多多线程的知识,其中有个问题,困扰我很久,不知道是什么原因,脑子一热,在传输过程中,添加了一句代码Thread.Sleep(0).那个问题竟然解决了,耗费我一上午 ...

  2. Java Thread 那些事

    这篇文章被压在草稿箱许久,最近公司内部的技术社区有同学贴出了几篇分享 Java线程的文章,发觉有很多概念没有讲清楚,所以花点时间继续撰写,便有了这篇博文. 本文只聚焦 JVM 层面的线程模型,不考虑和 ...

  3. 4.构造Thread对象你也许不知道的几件事

    1.Thread类对象只有在调用了start()方法之后,JVM虚拟机才会给我们创建一个真正的线程!否则就不能说是创建了线程!也就是说new Thread()之后,此时实际上在计算机底层,操作系统实际 ...

  4. java线程基础巩固---构造Thread对象你也许不知道的几件事

    关于Thread的构造在JDK文档中如下: 之后会把上面所有的构造都会学习到,这次主要是去研究一下图上标红的默认构造,当然大家肯定对于它都有些不屑,这有啥可学的,不new一个然后start线程不就启动 ...

  5. Android笔记——Handler Runnable与Thread的区别

    在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类是在java.lang包中定义的.一个类只要继承了Thread类同时覆写了本类中的run() ...

  6. 深入理解Thread.sleep的含义

    转载一篇对sleep说的非常好的一篇文章,原文http://www.cnblogs.com/ILove/archive/2008/04/07/1140419.html 我们可能经常会用到 Thread ...

  7. 漫谈c++11 Thread库之使写多线程程序

    c++11中最重要的特性之一就是对多线程的支持了,然而<c++ primer>5th却没有这部分内容的介绍,着实人有点遗憾.在网上了解到了一些关于thread库的内容.这是几个比较不错的学 ...

  8. org.hibernate.HibernateException: No Session found for current thread

    spring.springmvc和hibernate整合 在sessionFactory.getCurrentSession()时,出现以下异常 No Session found for curren ...

  9. Python爬虫爬取糗事百科段子内容

    参照网上的教程再做修改,抓取糗事百科段子(去除图片),详情见下面源码: #coding=utf-8#!/usr/bin/pythonimport urllibimport urllib2import ...

随机推荐

  1. [Angular] Upgrade existing Angular app to Progressive Web App

    If you alread have an existing Angular application and want to upgrade to progressive web app. 1. In ...

  2. PHP 7给我震撼

    看了一些php7(ng)的讨论,目前还没有去下beta版尝试编译. 作为一个phper,一直都有关注php本身语言的发展.以前在jumei工作的时候就听罗sir谈到过php ng,性能将超过faceb ...

  3. oracle rac下调节redo log file 文件大小

    rac下调节redo log file 文件大小 (1)查看当前日志信息: select * from v$logfile; (步骤2中得路径能够在这里MEMBER列看到,redo文件名称自己命名.比 ...

  4. 视差滚动demo (pc)

    根据设计图设定每屏的高度,js会自动缩放到全屏尺寸,效果要大尺寸才能看的出来 demo :http://runjs.cn/detail/uvizsekd <!DOCTYPE html> & ...

  5. HDU 5654 xiaoxin and his watermelon candy 离线树状数组

    xiaoxin and his watermelon candy Problem Description During his six grade summer vacation, xiaoxin g ...

  6. hdoj--3062--party(2-sat 可行解)

    Party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Subm ...

  7. 杂项-公司:YKK

    ylbtech-杂项-公司:YKK YKK的全称为Yoshida Kogyo Kabushikigaisha.YKK是拉链行业的鼻祖,代表着行业标准,因为采用日本精确的工艺,原料和管理方法,YKK价格 ...

  8. 40.DOM读取XML

    main.cpp #include <QtGui> #include <iostream> #include "domparser.h" int main( ...

  9. FMDB条件更新

    更新操作返回一个BOOL值,YES表示操作成功,NO表示执行过程遇到错误,可以通过-lastErrorMessage和-lastErrorCode查看错误信息.使用executeUpdate:方法执行 ...

  10. tomcat配置一个服务监听两个端口

    <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" ...