委託事件

http://www.cnblogs.com/sdya/p/5217635.html

反射

1 创建用于反射使用的DLL

新建一个C#类库项目,拷贝源代码如下,编译生成DLL(假如DLL的文件名是TestReflect.dll)

using System;
 2
 3namespace Webtest
 4{
 5 /// <summary>
 6 /// ReflectTest 的摘要说明。
 7 /// </summary>
 8 public class ReflectTest
 9 {
10  public ReflectTest()
11  {}
12
13  public string WriteString(string s)
14  {
15   return "欢迎您," + s;
16  }
17
18  /// <summary>
19  /// dsajkjflasjdfalksdjfaskfd
20  /// </summary>
21  /// <param name="s"></param>
22  /// <returns></returns>
23  public static string WriteName(string s)
24  {
25   return "欢迎您光临," + s;
26  }
27
28  public string WriteNoPara()
29  {
30   return "您使用的是无参数方法";
31  }
32 }
33}
34
35
36
3.多線程的例子
class Account
    {
        private Object thisLock = new object();
        int balance;
        Random r = new Random();

public Account(int initial)
        {
            balance = initial;
        }

int WithDraw(int amount)
        {
            if (balance < 0)
            {
                throw new Exception("负的Balance.");
            }
            //确保只有一个线程使用资源,一个进入临界状态,使用对象互斥锁,10个启动了的线程不能全部执行该方法
            lock (thisLock)
            {
                if (balance >= amount)
                {
                   
Console.WriteLine("----------------------------:" +
System.Threading.Thread.CurrentThread.Name + "---------------");

Console.WriteLine("调用Withdrawal之前的Balance:" + balance);
                    Console.WriteLine("把Amount输入 Withdrawal     :-" + amount);
                    //如果没有加对象互斥锁,则可能10个线程都执行下面的减法,加减法所耗时间片段非常小,可能多个线程同时执行,出现负数。
                    balance = balance - amount;
                    Console.WriteLine("调用Withdrawal之后的Balance :" + balance);
                    return amount;
                }
                else
                {
                    //最终结果
                    return 0;
                }
            }
        }
        public void DoTransactions()
        {
            for (int i = 0; i < 100; i++)
            {
                //生成balance的被减数amount的随机数
                WithDraw(r.Next(1, 100));
            }
        }
    }

class Program
    {
        static void Main(string[] args)
        {
            //初始化10个线程
            System.Threading.Thread[] threads = new System.Threading.Thread[10];
            //把balance初始化设定为1000
            Account acc = new Account(1000);
            for (int i = 0; i < 10; i++)
            {
                System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(acc.DoTransactions));
                threads[i] = t;
                threads[i].Name = "Thread" + i.ToString();
            }
            for (int i = 0; i < 10; i++)
            {
                threads[i].Start();
            }
            Console.ReadKey();
        }
    }

--來自 http://www.cnblogs.com/knowledgesea/archive/2012/11/22/2780651.html

1.进程:是操作系统结构的基础;是一个正在执行的程序;计算机中正在运行的程序实例;可以分配给处理器并由处理器执行的一个实体;由单一顺序的执行显示,一个当前状态和一组相关的系统资源所描述的活动单元。

2.线程:线程是程序中一个单一的顺序控制流程。是 程序执行流的最小单元。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源, 但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相 互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。

3.多线程:在单个程序中同时运行多个线程完成不同的工作,称为多线程。


小结:其实更容易理解一点进程与线程的话,可
以举这样一个例子:把进程理解成为一个运营着的公司,然而每一个公司员工就可以叫做一个进程。每个公司至少要有一个员工,员工越多,如果你的管理合理的
话,公司的运营速度就会越好。这里官味一点话就是说。cpu大部分时间处于空闲时间,浪费了cpu资源,多线程可以让一个程序“同时”处理多个事情,提高
效率。


单线程问题演示


创建一个WinForm应用程序,这里出现的问题是,点击按钮后如果在弹出提示框之前,窗体是不能被拖动的。

 private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 10000000000; i++)
{
i += 1;
}
MessageBox.Show("出现后能拖动,提示没出现之前窗体不能被拖动");
}

原因:运行这个应用程序的时候,窗体应用程序自带一个叫做UI的线程,这个线程负责窗体界面的移动大小等。如果点击按钮则这个线程就去处理这个循环计算,而放弃了其它操作,故而窗体拖动无响应。这就是单线程带来的问题。

解决办法:使用多线程,我们自己创建线程。把计算代码放入我们自己写的线程中,UI线程就能继续做他的界面响应了。


线程的创建


线程的实现:线程一定是要执行一段代码的,所以要产生一个线程,必须先为该线程写一个方法,这个方法中的代码,就是该线程中要执行的代码,然而启动线程时,是通过委托调用该方法的。线程启动是,调用传过来的委托,委托就会执行相应的方法,从而实现线程执行方法。

 //创建线程
private void button1_Click(object sender, EventArgs e)
{
//ThreadStart是一个无参无返回值的委托。
ThreadStart ts = new ThreadStart(js);// ThreadStart ts = js; 一樣的效果
//初始化Thread的新实例,并通过构造方法将委托ts做为参数赋初始值。
Thread td = new Thread(ts); //需要引入System.Threading命名空间
//运行委托
td.Start();
}
//创建的线程要执行的函数。
void js()
{
for (int i = 0; i < 1000000000; i++)
{
i += 1;
}
MessageBox.Show("提示出现前后窗体都能被拖动");
}

把这个计算写入自己写的线程中,就解决了单线程中的界面无反应缺陷。


小结:创建线程的4个步骤:1.编写线程索要执行的方法。2.引用System.Threading命名空。3.实例化Thread类,并传入一个指向线程所要运行方法的委托。4.调用Start()方法,将该线程标记为可以运行的状态,但具体执行时间由cpu决定。


 方法重入(多个线程执行一个方法)


由于线程可与同属一个进程的其它线程共享进程所拥有的全部资源。

所以多个线程同时执行一个方法的情况是存在的,然而这里不经过处理的话会出现一点问题,线程之间先后争抢资源,致使数据计算结果错乱。

 public partial class 方法重入 : Form
{
public 方法重入()
{
InitializeComponent(); //设置TextBox类的这个属性是因为,开启ui线程,
//微软设置检测不允许其它线程对ui线程的数据进行访问,这里我们把检测关闭,也就允许了其它线程对ui线程数据的访问。
//如果检测不设置为False,则报错。
TextBox.CheckForIllegalCrossThreadCalls = false;
} private void button1_Click(object sender, EventArgs e)
{
textBox1.Text = "0";
//开启第一个线程,对js方法进行计算
ThreadStart ts = new ThreadStart(js);
Thread td = new Thread(ts);
td.Start(); //开启第二个线程,对js方法进行计算
ThreadStart ts1 = new ThreadStart(js);
Thread td1 = new Thread(ts1);
td1.Start();
}
//多线程要重入的方法。
void js()
{
int a = Convert.ToInt32(textBox1.Text);
for (int i = 0; i < 2000; i++)
{
a++;
textBox1.Text = a.ToString();
}
}

出错现象:点击按钮后TextBox1中数据为2000+或2000,如果你看到的数据一直是2000说明你的计算机cpu比较牛X,这样的话你想 看到不是2000的话,你可以多点击几次试试,真不行的话,代码中给TextBox1赋值为0,换做在界面中给textBox1数值默认值为0试试看。

出错原因:两个进程同时计算这个方法,不相干扰应该每个线程计算的结果都是2000的,但是这里的结果输出却让人以外,原因是第一个两个线程同时计 算,并不是同时开始计算,而是根据cpu决定的哪个先开始,哪个后开始,虽然相差时间不多,但后开始的就会取用先开始计算过的数据计算,这样就会导致计算 错乱。

解决办法:解决这个的一个简单办法解释给方法加锁,加锁的意思就是第一个线程取用过这个资源完毕后,第二个线程再来取用此资源。形成排队效果。

下面给方法加锁。

//多线程要重入的方法,这里加锁。
void js()
{
lock (this)
{
int a = Convert.ToInt32(textBox1.Text);
for (int i = 0; i < 2000; i++)
{
a++;
textBox1.Text = a.ToString();
}
}
}

给方法加过锁后,线程一前一后取用资源,就能避免不可预计的错乱结果,第一个线程计算为2000,第二个线程计算就是从2000开始,这里的结果就为4000。


小结:多线程可以同时运行,提高了cpu的效率,这里的同时并不是同时开始,同时结束,他们的开始是由cpu决定的,时间相差不大,但会有不可预计的计算错乱,这里要注意类似上面例子导致的方法重入问题。


前台线程后台线程


.Net的公用语言运行时能区分两种不同类型的线程:前台线程和后台线程。这两者的区别就是:应用程序必须运行完所有的前台线程才可以退出;而对于后台线程,应用程序则可以不考虑其是否已经运行完毕而直接退出,所有的后台线程在应用程序退出时都会自动结束。

问题:关闭了窗口,消息框还能弹出。

  private void button1_Click(object sender, EventArgs e)
{
//开启一个线程,对js方法进行计算
ThreadStart ts2 = new ThreadStart(js);
Thread td2 = new Thread(ts2);
td2.Start(); }
void js()
{
for (int i = 0; i < 2000000000; i++) //如果看不出效果这里的2后面多加0
{
i++;
}
MessageBox.Show("关闭了窗口我还是要出来的!");
}

原因:.Net环境使用Thread建立线程,线程默认为前台线程。即线程属性IsBackground=false,而前台线程只要有一个在运行则应用程序不关闭,所以知道弹出消息框后应用程序才算关闭。

解决办法:在代码中设置td2.IsBackground=true;


线程执行带参数的方法


 //创建一个执行带参数方法的线程
private void button1_Click(object sender, EventArgs e)
{
//ParameterizedThreadStart这是一个参数类型为object的委托
ParameterizedThreadStart pts=new ParameterizedThreadStart(SayHello);
Thread td2 = new Thread(pts);
td2.Start("张三"); //参数值先入这里
}
void SayHello(object name)
{
MessageBox.Show("你好,"+name.ToString()+"!");

线程执行带多参数的方法


其实还是带一参数的方法,只不过是利用参数类型为object的好处,这里将类型传为list类型,貌似多参。

        //创建一个执行带多个参数的方法线程
private void button1_Click(object sender, EventArgs e)
{
List<string> list = new List<string> { "张三", "李四", "王五" };
//ParameterizedThreadStart这是一个参数类型为object的委托
ParameterizedThreadStart pts=new ParameterizedThreadStart(SayHello);
Thread td2 = new Thread(pts);
td2.Start(list); //参数值先入这里
}
void SayHello(object list)
{
List<string> lt = list as List<string>;
for (int i = 0; i < lt.Count; i++)
{
MessageBox.Show("你好," + lt[i].ToString() + "!");
}


总结:看到这里相信对多线程应该有一个初步的了解了,我就不说了。

2 应用于反射的例子

在ASPNET页面中加入以下函数:

public void test1()
   {
  System.Reflection.Assembly ass;
  Type type ;
 object obj;
   try
  {
   ass = System.Reflection.Assembly.LoadFile(@"d:\TestReflect.dll");
   type = ass.GetType("Webtest.ReflectTest");//必须使用名称空间+类名称
    System.Reflection.MethodInfo method = type.GetMethod("WriteString");//方法的名称
   obj = ass.CreateInstance("Webtest.ReflectTest");//必须使用名称空间+类名称
   string s = (string)method.Invoke(obj,new string[]{"jianglijun"}); //实例方法的调用
  
   Response.Write(s+"<br>");
   method = type.GetMethod("WriteName");//方法的名称
   s = (string)method.Invoke(null,new string[]{"jianglijun"}); //静态方法的调用
    Response.Write(s+"<br>");

method = type.GetMethod("WriteNoPara");//无参数的实例方法
    s = (string)method.Invoke(obj,null);
    Response.Write(s+"<br>");
   method = null;
  }
 catch(Exception ex)
  {
   Response.Write(ex+"<br>"); }33   }34  }

4.項目編碼
C#中怎么设置编码
先说一下编码这块啊,不管你是HttpWebRequest还是Socket方法,都需要设置发送和接收时的编码格式,否则会出现乱码的
HttpWebRequest的解决方法大家可以参考我的文章:C#httphelper类 这里有解决编码的问题,也做到了无视编码的方式。
我们常用的编码有
utf-8,gb2312,gbk等这几种。
在C#中是通过一个类来确定的,
那就是 System.Text.Encoding
大部分情况下我们可以使用  System.Text.Encoding.UTF8来设置编码,
但是有时候也需要这个方法
System.Text.Encoding.GetEncoding("你的编码名称");
怎么把字符转成相就的编码格式呢?
这个更简单
我们可以有两种方法
第一种

[C#] 纯文本查看 复制代码
01
Byte[] MyData = System.Text.Encoding.UTF8.GetBytes(“你的字符串”);

第二种

[C#] 纯文本查看 复制代码
01
System.Text.Encoding.GetEncoding("").GetBytes(“你的字符串”);

例子

class Program
    {
        private static object lockthis = new object();
        static void Main(string[] args)
        {
            ThreadStart ts = abc;
            Thread td = new Thread(ts);
            td.Start();
            ThreadStart tstwo = abc;
            Thread tdtwo = new Thread(tstwo);
            tdtwo.Start();
            Console.ReadKey();
        }

public static void abc()
        {

lock (lockthis)
            {
            for (int i = 1; i < 100; i++)
            {
                Console.WriteLine(i);
            }
            }
        }
    }

这种情况是对线程进行了上锁,那么会执行1-99,然后在执行1-99

class Program
    {
        static void Main(string[] args)
        {
            ThreadStart ts = abc;
            Thread td = new Thread(ts);
            td.Start();
            ThreadStart tstwo = abc;
            Thread tdtwo = new Thread(tstwo);
            tdtwo.Start();
            Console.ReadKey();
        }

public static void abc()
        {
            for (int i = 1; i < 100; i++)
            {
                Console.WriteLine(i);
            }
           
        }
    }

这里不加任何限制那么两个线程一起跑,那么打印出来的数字是没有规律的.

C#容易忽略點--包含多線程 委託事件等等--此頁面bug,編輯能查看全部內容的更多相关文章

  1. C# 多線程&BackgroundWorker概念入門教程

    感謝以下各位作者的貢獻~ 百度經驗舉了個例子,很好理解BackgroundWorker的用途(主要是用來啟動後台線程,而不阻塞調用程式的運行),收藏一下  http://jingyan.baidu.c ...

  2. 開啟windows 7 ,10 的熱點功能(無線熱點)

    開啟windows 7 ,10 的熱點功能: 1.首先要確定你的電腦無線芯片有無熱點功能  # netsh wlan show drivers    Hosted network supported ...

  3. JS常用的腳本庫--包括在線編輯器

    原文链接 一.基本库 1.jQuery a.简介 JQuery是继prototype之后又一个优秀的Javascript库.它是轻量级的js库 ,它兼容CSS3,还兼容各种浏览器(IE 6.0+, F ...

  4. html contenteditable

    contenteditable 是html中的一個屬性,在HTML中,某些元素設置 contenteditable='true'  屬性時可以開啟該元素的編輯模式,contenteditable 可以 ...

  5. cron_action

    crontab   using shell script to automate linux system maintenance tasks Linux中用crontab例行工作安排_Linux教程 ...

  6. 如何让Asp.net webAPI返回JSON格式数据

    ASP.NET Web API 是新一代的 HTTP 網路服務開發框架,除了可以透過 Visual Studio 2012 快速開發外 (內建於 ASP.NET MVC 4 的 Web API 專案範 ...

  7. 如何在 Visual Studio 2012 控制 TFS 版控時要忽略哪些檔案

    幾乎在任何一種版本控管的機制裡,都會遇到那些「不應該簽入到版本庫」的潛規則,以往我們在用 SVN 的時候,我就寫過幾篇文章要大家注意這點.最近都改用 TFS 做版控,因為大多使用 Visual Stu ...

  8. GOOGLE搜索從入門到精通V4.0

    1,前言2,摘要3,如何使用本文4,Google簡介5,搜索入門6,初階搜索 6.1,搜索結果要求包含兩個及兩個以上關鍵字 6.2,搜索結果要求不包含某些特定資訊 6.3,搜索結果至少包含多個關鍵字中 ...

  9. mootools vs jquery

    大部分最近才剛接觸JavaScript的人會面臨到的困難是該選擇哪個套件(library)或是該先學哪個套件.如果你在一間公司裡上班,那麼可能公司已經有一套固定使用的套件,若是在這種情況下,問題就沒那 ...

随机推荐

  1. HDU 4441 Queue Sequence(splay)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4441 题意:一个数列,三种操作:(1)插入:找到没在当前数列中的最小的正整数i,将其插在位置p之后,并 ...

  2. BZOJ 3674: 可持久化并查集加强版

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3674 题意:三种操作:(1)合并ab所在集合:(2)查询ab是否在一个集合:(3) ...

  3. CSS的单位及css3的calc()及line-height百分比

    锚点:css中百分比减去固定元素 单位介绍 说到css的单位,大家应该首先想到的是px,也就是像素,我们在网页布局中一般都是用px,但是近年来自适应网页布局越来越多,em和百分比也经常用到了.然后随着 ...

  4. I2C总线信号时序总结

    I2C总线信号时序总结 总线空闲状态  I2C总线总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态.此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电 ...

  5. poj 1502 最短路+坑爹题意

    链接:http://poj.org/problem?id=1502 MPI Maelstrom Time Limit: 1000MS   Memory Limit: 10000K Total Subm ...

  6. hdu 4828 Grids 卡特兰数+逆元

    Grids Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Problem D ...

  7. Android中四种OnClick事件的写法

    package com.example.dailphone; import android.support.v7.app.ActionBarActivity; import android.suppo ...

  8. Entity Framework(1)

    Web.Config配置 <dataConfiguration defaultDatabase="strConn"> <providerMappings> ...

  9. Linux_常用命令_03_磁盘/挂载_信息查看

    1. 1.1. mount 不带参数的话,显示的是 当前已经挂载的情况 1.2. df 不带参数的话,硬盘分区状况查询 2. 2.1. cat /proc/partitions 2.2. fdisk ...

  10. poj2780Linearity(多点共线)

    链接 判断最多多少点在一条直线上, 可以枚举每一个点为坐标系的原点,其它点变成相应的位置,然后求得过原点及其点的斜率,排序找一下最多相同的. #include <iostream> #in ...