精华内容
下载资源
问答
  • Winform多线程问题

    万次阅读 2010-11-10 17:07:00
    线程的常用操作有:启动线程、终止线程、合并线程和让线程休眠等。 1. 启动线程  在使用线程前,首先要创建一个线程。其一般形式为: Thread t=new Thread(enterPoint);  其中enterPoint为线程...

    System.Threading命名空间下,包含了用于创建和控制线程的Thread类。对线程的常用操作有:启动线程、终止线程、合并线程和让线程休眠等。

        1. 启动线程

        在使用线程前,首先要创建一个线程。其一般形式为:

    Thread t=new Thread(enterPoint);

        其中enterPoint为线程的入口,即线程开始执行的方法。在托管代码中,通过委托处理线程执行的代码。例如:

    Thread t=new Thread(new ThreadStart(methodName));

        创建线程实例后,就可以调用Start方法启动线程了。

        2. 终止线程

        线程启动后,当不需要某个线程继续执行的时候,有两种终止线程的方法。

        一种是事先设置一个布尔变量,在其他线程中通过修改该变量的值作为传递给该线程是否需要终止的判断条件,而在该线程中循环判断该条件,以确定是否退出线程,这是结束线程的比较好的方法,实际编程中一般使用这种方法。

        第二种方法是通过调用Thread类的Abort方法强行终止线程。例如:

    t.Abort();

        Abort方法没有任何参数,线程一旦被终止,就无法再重新启动。由于Abort通过抛出异常强行终止结束线程,因此在实际编程中,应该尽量避免采用这种方法。

        调用Abort方法终止线程时,公共语言运行库(CLR)会引发ThreadAbortException异常,程序员可以在线程中捕获ThreadAbortException异常,然后在异常处理的Catch块或者Finally块中作释放资源等代码处理工作;但是,线程中也可以不捕获ThreadAbortException异常,而由系统自动进行释放资源等处理工作。

        注意,如果线程中捕获了ThreadAbortException异常,系统在finally子句的结尾处会再次引发ThreadAbortException异常,如果没有finally子句,则会在Catch子句的结尾处再次引发该异常。为了避免再次引发异常,可以在finally子句的结尾处或者Catch子句的结尾处调用System.Threading.Thread.ResetAbort方法防止系统再次引发该异常。

        使用Abort方法终止线程,调用Abort方法后,线程不一定会立即结束。这是因为系统在结束线程前要进行代码清理等工作,这种机制可以使线程的终止比较安全,但清理代码需要一定的时间,而我们并不知道这个工作将需要多长时间。因此,调用了线程的Abort方法后,如果系统自动清理代码的工作没有结束,可能会出现类似死机一样的假象。为了解决这个问题,可以在主线程中调用子线程对象的Join方法,并在Join方法中指定主线程等待子线程结束的等待时间。

        3. 合并线程

        Join方法用于把两个并行执行的线程合并为一个单个的线程。如果一个线程t1在执行的过程中需要等待另一个线程t2结束后才能继续执行,可以在t1的程序模块中调用t2join()方法。例如:

        t2.Join();

        这样t1在执行到t2.Join()语句后就会处于阻塞状态,直到t2结束后才会继续执行。

        但是假如t2一直不结束,那么等待就没有意义了。为了解决这个问题,可以在调用t2Join方法的时候指定一个等待时间,这样t1这个线程就不会一直等待下去了。例如,如果希望将t2合并到t1后,t1只等待100毫秒,然后不论t2是否结束,t1都继续执行,就可以在t1中加上语句:

        t2.Join(100);

        Join方法通常和Abort一起使用。

        由于调用某个线程的Abort方法后,我们无法确定系统清理代码的工作什么时候才能结束,因此如果希望主线程调用了子线程的Abort方法后,主线程不必一直等待,可以调用子线程的Join方法将子线程连接到主线程中,并在连接方法中指定一个最大等待时间,这样就能使主线程继续执行了。

        4. 让线程休眠

        在多线程应用程序中,有时候并不希望某一个线程继续执行,而是希望该线程暂停一段时间,等待其他线程执行之后再继续执行。这时可以调用Thread类的Sleep方法,即让线程休眠。例如:

    Thread.Sleep(1000);

        这条语句的功能是让当前线程休眠1000毫秒。

        注意,调用Sleep方法的是类本身,而不是类的实例。休眠的是该语句所在的线程,而不是其他线程。

        5. 线程优先级

        当线程之间争夺CPU时间片时,CPU是按照线程的优先级进行服务的。在C#应用程序中,可以对线程设定五个不同的优先级,由高到低分别是HighestAboveNormalNormalBelowNormalLowest。在创建线程时如果不指定其优先级,则系统默认为Normal。假如想让一些重要的线程优先执行,可以使用下面的方法为其赋予较高的优先级:

    Thread t=new Thread(new ThreadStart(enterpoint));

    t.priority=ThreadPriority.AboveNormal;

        通过设置线程的优先级可以改变线程的执行顺序,所设置的优先级仅仅适用于这些线程所属的进程。

        注意,当把某线程的优先级设置为Highest时,系统上正在运行的其他线程都会终止,所以使用这个优先级别时要特别小心。

        6. 线程池

        线程池是一种多线程处理形式,为了提高系统性能,在许多地方都要用到线程池技术。例如,在一个C/S模式的应用程序中的服务器端,如果每到一个请求就创建一个新线程,然后在新线程中为其请求服务的话,将不可避免的造成系统开销的增大。实际上,创建太多的线程可能会导致由于过度使用系统资源而耗尽内存。为了防止资源不足,服务器端应用程序应采取一定的办法来限制同一时刻处理的线程数目。

        线程池为线程生命周期的开销问题和资源不足问题提供了很好的解决方案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。其好处是,由于请求到达时线程已经存在,所以无意中也就消除了线程创建所带来的延迟。这样,就可以立即为新线程请求服务,使其应用程序响应更快。而且,通过适当地调整线程池中的线程数目,也就是当请求的数目超过了规定的最大数目时,就强制其他任何新到的请求一直等待,直到获得一个线程来处理为止,从而可以防止资源不足。

        线程池适用于需要多个线程而实际执行时间又不多的场合,比如有些常处于阻塞状态的线程。当一个应用程序服务器接受大量短小线程的请求时,使用线程池技术是非常合适的,它可以大大减少线程创建和销毁的次数,从而提高服务器的工作效率。但是如果线程要求运行的时间比较长的话,那么此时线程的运行时间比线程的创建时间要长得多,仅靠减少线程的创建时间对系统效率的提高就不是那么明显了,此时就不适合使用线程池技术,而需要借助其他的技术来提高服务器的服务效率。

        7. 同步

        同步是多线程中一个非常重要的概念。所谓同步,是指多个线程之间存在先后执行顺序的关联关系。如果一个线程必须在另一个线程完成某个工作后才能继续执行,则必须考虑如何让其保持同步,以确保在系统上同时运行多个线程而不会出现逻辑错误。

        当两个线程t1t2有相同的优先级,并且同时在系统上运行时,如果先把时间片分给t1使用,它在变量variable1中写入某个值,但如果在时间片用完时它仍没有完成写入,这时由于时间片已经分给t2使用,而t2又恰好要尝试读取该变量,它可能就会读出错误的值。这时,如果使用同步仅允许一个线程使用variable1,在该线程完成对variable1的写入工作后再让t2读取这个值,就可以避免出现此类错误。

        为了对线程中的同步对象进行操作,C#提供了lock语句锁定需要同步的对象。lock关键字确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻塞),直到该对象被释放。比如线程t1variable1操作时,为了避免其他线程也对其进行操作,可以使用lock语句锁定variable1,实现代码为:

    lock(variable1)

    {

        variable1++;

    }

        注意,锁定的对象一定要声明为private,不要锁定public类型的对象,否则将会使lock语句无法控制,从而引发一系列问题。

        另外还要注意,由于锁定一个对象之后,其他任何线程都不能访问这个对象,需要使用该对象的线程就只能等待该对象被解除锁定后才能使用。因此如果在锁定和解锁期间处理的对象过多,就会降低应用程序的性能。

        还有,如果两个不同的线程同时锁定两个不同的变量,而每个线程又都希望在锁定期间访问对方锁定的变量,那么两个线程在得到对方变量的访问权之前都不会释放自己锁定的对象,从而产生死锁。在编写程序时,要注意避免这类操作引起的问题。

        【例1-2】线程的基本用法。

        (1) 新建一个名为ThreadExampleWindows应用程序,界面设计如图1-2所示。

    1-2  1-2的设计界面
    1-3  1-2的运行界面

        (2) 向设计窗体拖放一个Timer组件,不改变自动生成的对象名。

        (3) 添加命名空间引用:

    using System.Threading;

        (4) 在构造函数上方添加字段声明:

    StringBuilder sb = new StringBuilder();

    Thread thread1;

    Thread thread2;

        (5) 直接添加代码:

    private void AppendString(string s)

    {

        lock(sb)

        {

            sb.Append(s);

        }

    }

    public void Method1()

    {

        while(true)

        {

            Thread.Sleep(100);   //线程休眠100毫秒

            AppendString("a");

        }

    }

    public void Method2()

    {

        while(true)

        {

            Thread.Sleep(100);   //线程休眠100毫秒

            AppendString("b");

        }

    }

        (6) 分别在【启动线程】和【终止线程】按钮的Click事件中添加代码:

    private void buttonStart_Click(object sender, EventArgs e)

    {

        sb.Remove(0, sb.Length);

        timer1.Enabled = true;

        thread1 = new Thread(new ThreadStart(Method1));

        thread2 = new Thread(new ThreadStart(Method2));

        thread1.Start();

        thread2.Start();

    }

    private void buttonAbort_Click(object sender, EventArgs e)

    {

        thread1.Abort();

        thread1.Join(10);

        thread2.Abort();

        thread2.Join(10);

    }

        (7) timer1Tick事件中添加代码:

    private void timer1_Tick(object sender, EventArgs e)

    {

        if (thread1.IsAlive == true || thread2.IsAlive == true)

        {

            richTextBox1.Text = sb.ToString();

        }

        else

        {

            timer1.Enabled = false;

        }

    }

        (8) <F5>键编译并执行,单击【启动线程】后,再单击【终止线程】,从图1-3所示的运行结果中可以看到,两个具有相同优先级的线程同时执行时,在richTextBox1中添加的字符个数基本上相同。

    1.1.3  在一个线程中操作另一个线程的控件

        默认情况下,C#不允许在一个线程中直接操作另一个线程中的控件,这是因为访问Windows窗体控件本质上不是线程安全的。如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。还可能出现其他与线程相关的bug,以及不同线程争用控件引起的死锁问题。因此确保以线程安全方式访问控件非常重要。

        在调试器中运行应用程序时,如果创建某控件的线程之外的其他线程试图调用该控件,则调试器会引发一个InvalidOperationException异常,并提示消息:“从不是创建控件的线程访问它”。

        但是在Windows应用程序中,为了在窗体上显示线程中处理的信息,我们可能需要经常在一个线程中引用另一个线程中的窗体控件。比较常用的办法之一是使用委托(delegate)来完成这个工作。

        为了区别是否是创建控件的线程访问该控件对象,Windows应用程序中的每一个控件对象都有一个InvokeRequired属性,用于检查是否需要通过调用Invoke方法完成其他线程对该控件的操作,如果该属性为true,说明是其他线程操作该控件,这时可以创建一个委托实例,然后调用控件对象的Invoke方法,并传入需要的参数完成相应操作,否则可以直接对该控件对象进行操作,从而保证了安全代码下线程间的互操作。例如:

    delegate void AppendStringDelegate(string str);

    private void AppendString(string str)

    {

        if (richTextBox1.InvokeRequired)

        {

            AppendStringDelegate d = new AppendStringDelegate(AppendString);

            richTextBox1.Invoke(d, "abc");

        }

        else

        {

            richTextBox1.Text += str;

        }

    }

        这段代码中,首先判断是否需要通过委托调用对richTextBox1的操作,如果需要,则创建一个委托实例,并传入需要的参数完成else代码块的功能;否则直接执行else代码块中的内容。

        实际上,由于我们在编写程序时就已经知道控件是在哪个线程中创建的,因此也可以在不是创建控件的线程中直接调用控件对象的Invoke方法完成对该线程中的控件的操作。

        注意,不论是否判断InvokeRequired属性,委托中参数的个数和类型必须与传递给委托的方法需要的参数个数和类型完全相同。

        【例1-3】一个线程操作另一个线程的控件的方法。

        (1) 新建一个名为ThreadControlExampleWindows应用程序,界面设计如图1-4所示。

    1-4  1-3的设计界面
    1-5  1-3的运行界面

        (2) 添加命名空间引用:

    using System.Threading;

     

        (3) 在构造函数上方添加字段声明,并在构造函数中初始化对象:

    Thread thread1;

    Thread thread2;

    delegate void AppendStringDelegate(string str);

    AppendStringDelegate appendStringDelegate;

    public Form1()

    {

        InitializeComponent();

        appendStringDelegate = new AppendStringDelegate(AppendString);

    }

     

        (4) 直接添加代码:

    private void AppendString(string str)

    {

        richTextBox1.Text += str;

    }

    private void Method1()

    {

        while (true)

        {

            Thread.Sleep(100);   //线程1休眠100毫秒

            richTextBox1.Invoke(appendStringDelegate, "a");

        }

    }

    private void Method2()

    {

        while (true)

        {

            Thread.Sleep(100);   //线程2休眠100毫秒

            richTextBox1.Invoke(appendStringDelegate, "b");

        }

    }

        (5) 分别在【启动线程】和【终止线程】按钮的Click事件中添加代码:

    private void buttonStart_Click(object sender, EventArgs e)

    {

        richTextBox1.Text = "";

        thread1 = new Thread(new ThreadStart(Method1));

        thread2 = new Thread(new ThreadStart(Method2));

        thread1.Start();

        thread2.Start();

     

    }

     

    private void buttonStop_Click(object sender, EventArgs e)

    {

        thread1.Abort();

        thread1.Join();

        thread2.Abort();

        thread2.Join();

        MessageBox.Show("线程12终止成功");

     

    }

        (6) <F5>键编译并执行,单击【启动线程】后,再单击【终止线程】,运行结果如图1-5所示。

    转自

    1-4  1-3的设计界面
    1-5  1-3的运行界面
    C#网络应用高级编程

        编著

    展开全文
  • 首先新建一个winform程序,什么都不用设置,直接设置窗体的属性, 有一个FormBorderStyle这个属性,选择none。这样就不会出现关闭最小化最大化的一些按钮了。 再选择另一个属性。 设置Size为0,0。这样...
    展开全文
  • 最近在学习C# 多线程相关知识,这块一直比较薄弱,在网上查了一下资料,学习了一下前辈们的经验,小弟自己也比葫芦画瓢的写了一个,自学一下。 代码如下 1 using System; 2 using System.Collections....

    最近在学习C# 多线程相关知识,这块一直比较薄弱,在网上查了一下资料,学习了一下前辈们的经验,小弟自己也比葫芦画瓢的写了一个,自学一下。

     

    代码如下

      1 using System;
      2 using System.Collections.Generic;
      3 using System.ComponentModel;
      4 using System.Data;
      5 using System.Drawing;
      6 using System.Linq;
      7 using System.Text;
      8 using System.Threading;
      9 using System.Threading.Tasks;
     10 using System.Windows.Forms;
     11 
     12 namespace WindowsFormsApp1
     13 {
     14     public partial class Form1 : Form
     15     {
     16         public Form1()
     17         {
     18             InitializeComponent();
     19         }
     20 
     21         
     22 
     23         //声明线程数组1
     24         Thread[] thread1 = new Thread[1];
     25 
     26         //声明线程数组2
     27         Thread[] thread2 = new Thread[1];
     28 
     29 
     30 
     31         //声明委托,为listbox1增加Item
     32         delegate void AddItemMethod1(string txt);
     33 
     34         //声明委托,为listbox2增加Item
     35         delegate void AddItemMethod2(string txt);
     36 
     37         //利用线程为Listbox1添加内容
     38         private void AddItem1(string txt)
     39         {
     40             if (this.InvokeRequired)
     41             {
     42                 AddItemMethod1 d = new AddItemMethod1(AddItem1);
     43                 this.Invoke(d, new object[] { txt });
     44             }
     45             else
     46             {
     47                 this.listBox1.Items.Add(txt);
     48             }
     49         }
     50 
     51         //利用线程为Listbox2添加内容
     52         private void AddItem2(string txt)
     53         {
     54             if (this.InvokeRequired)
     55             {
     56                 AddItemMethod2 d = new AddItemMethod2(AddItem2);
     57                 this.Invoke(d, new object[] { txt });
     58             }
     59             else
     60             {
     61                 this.listBox2.Items.Add(txt);
     62             }
     63         }
     64 
     65         //生成Item
     66         public void GetItem1()
     67         {
     68             while (true)
     69             {
     70                 AddItem1("OK");
     71                 Thread.Sleep(1000);
     72             }
     73         }
     74 
     75         //生成Item
     76         public void GetItem2()
     77         {
     78             while (true)
     79             {
     80                 AddItem2("NICE");
     81                 Thread.Sleep(5000);
     82             }
     83         }
     84 
     85         private void button1_Click(object sender, EventArgs e)
     86         {
     87             ////循环创建并启动线程1
     88             for (int i = 0; i < thread1.Length; i++)
     89             {
     90                 if (thread1[i] == null)//线程不存在
     91                 {
     92                     thread1[i] = new Thread(new ThreadStart(() =>
     93                     {
     94                         while (true)
     95                         {
     96                             AddItem1("OK");
     97                             Thread.Sleep(1000);
     98                             //listbox1 的Item数量到20个是停止thread1
     99                             if (listBox1.Items.Count >10)
    100                             {
    101 
    102                                 if (i >= thread1.Length)
    103                                 {
    104                                     i = thread1.Length - 1;
    105                                 }
    106                                 //如果不加上面的判断,下面就会提示索引超出数组长度界限,我定义了thread1 的线程个数是1个,for循环中i为1的情况应该是进不来的,为啥
    107                                 // 下面的i会是1??
    108                                 thread1[i].Abort();
    109                             }
    110                         }
    111                     }));
    112                     thread1[i].Name = i.ToString();
    113                     thread1[i].Start();
    114                 }
    115                 else
    116                 {
    117                     //已经存在,如果没有运行,则启动  
    118                     if (thread1[i].ThreadState == ThreadState.Aborted || thread1[i].ThreadState == ThreadState.Stopped)
    119                     {
    120                         thread1[i] = new Thread(new ThreadStart(GetItem1));
    121                         thread1[i].Name = i.ToString();
    122                         thread1[i].Start();
    123                     }
    124                     else
    125                     {
    126                         thread1[i].Start();
    127                     }
    128                 }
    129             }
    130 
    131 
    132             ////循环创建并启动线程2
    133             for (int j = 0; j < thread2.Length; j++)
    134             {
    135                 if (thread2[j] == null)//线程不存在
    136                 {
    137                     thread2[j] = new Thread(new ThreadStart(GetItem2));
    138                     thread2[j].Name = j.ToString();
    139                     thread2[j].Start();
    140                 }
    141                 else
    142                 {
    143                     //已经存在,如果没有运行,则启动  
    144                     if (thread2[j].ThreadState == ThreadState.Aborted || thread2[j].ThreadState == ThreadState.Stopped)
    145                     {
    146                         thread2[j] = new Thread(new ThreadStart(GetItem2));
    147                         thread2[j].Name = j.ToString();
    148                         thread2[j].Start();
    149                     }
    150                     else
    151                     {
    152                         thread2[j].Start();
    153                     }
    154                 }
    155             }
    156         }
    157 
    158         private void button2_Click(object sender, EventArgs e)
    159         {
    160             //循环停止线程1执行  
    161             for (int i = 0; i < thread1.Length; i++)
    162             {
    163                 //如果线程存在,并且状态不是停止也不是终止的,则终止该线程  
    164                 if (thread1[i] != null && thread1[i].ThreadState != ThreadState.Stopped && thread1[i].ThreadState != ThreadState.Aborted)
    165                 {
    166                     thread1[i].Abort();
    167                 }
    168             }
    169 
    170             //循环停止线程2执行  
    171             for (int j = 0; j < thread2.Length; j++)
    172             {
    173                 //如果线程存在,并且状态不是停止也不是终止的,则终止该线程  
    174                 if (thread2[j] != null && thread2[j].ThreadState != ThreadState.Stopped && thread2[j].ThreadState != ThreadState.Aborted)
    175                 {
    176                     thread2[j].Abort();
    177                 }
    178             }
    179         }
    180     }
    181 }
    View Code

     

    转载于:https://www.cnblogs.com/zyfadmin/p/8395216.html

    展开全文
  • 今天碰到一个很蛋疼的需求:运行一个exe把指定文件上传到一个内部的文件系统里去,并把exe返回的信息通过...在UI线程上面我们可以直接通过System.Windows.Forms.Clipboard.GetText()拿到Clipboard里面的文本,但是...

    今天碰到一个很蛋疼的需求:运行一个exe把指定文件上传到一个内部的文件系统里去,并把exe返回的信息通过email发出去。

    1. exe的返回信息是保存在Clipboard里面的。这个很蛋疼!!!

    2. 运行exe/发送email必须是异步的。

    在UI线程上面我们可以直接通过System.Windows.Forms.Clipboard.GetText()拿到Clipboard里面的文本,但是在后台线程里是不能访问Clipboard的(Clipboard.GetText()永远返回null)。Google完解决方案如下:

    View Code
     1     class ClipboardAsync
    2 {
    3 private string _getText;
    4 private void ThGetText(object format)
    5 {
    6 try
    7 {
    8 _getText = format == null ? Clipboard.GetText() : Clipboard.GetText((TextDataFormat)format);
    9 }
    10 catch
    11 {
    12 _getText = null;
    13 }
    14 }
    15
    16 public static string GetText()
    17 {
    18 var instance = new ClipboardAsync();
    19 var staThread = new Thread(instance.ThGetText);
    20 staThread.SetApartmentState(ApartmentState.STA);
    21 staThread.Start();
    22 staThread.Join();
    23 return instance._getText;
    24 }
    25
    26 public static string GetText(TextDataFormat format)
    27 {
    28 var instance = new ClipboardAsync();
    29 var staThread = new Thread(instance.ThGetText);
    30 staThread.SetApartmentState(ApartmentState.STA);
    31 staThread.Start(format);
    32 staThread.Join();
    33 return instance._getText;
    34 }
    35 }

    转载于:https://www.cnblogs.com/sstar/archive/2012/04/06/2435031.html

    展开全文
  • c#之winform窗体多线程Thread应用

    千次阅读 2019-03-15 16:15:08
    多线程的应用 在面向对象编程中,经常会面对创建对象和销毁对象的情况,如果不正确处理的话,在短时间内创建大量对象然后执行简单处理之后又要销毁这些刚刚建立的对象,这是一个非常消耗性能的低效行为,所以很多...
  • 话不说,先上代码。(纯手打,有错误请指出来) //导入按钮点击事件 private void btn_import_Click(object sender,EventArgs e) { //1.绑定需要执行的操作方法 var act = new Action(Import); act....
  • 3)如果当线程,直接委托实现就可以,如果多线程,用invoke技术在多线程编程中,我们经常要在工作线程中去更新界面显示,而在多线程中直接调用界面控件的方法是错误的做法,Invoke 和 BeginInvoke 就是为了解决这个...
  • winform多线程

    千次阅读 2017-08-28 10:19:45
    最近在做winform的项目用到了多线程,刚好看到这个还不错就copy下来可以以后看一下。 单线程的winfom程序中,设置一个控件的值是很easy的事情,直接 this.TextBox1.value = "Hello World!";就搞定了,但是如果在...
  • WinForm多线程学习文档

    2019-09-22 07:58:02
    目录 基础篇 怎样创建一个线程 受托管的线程与 Windows线程 ...前台线程与后台线程 ...异步和多线程有什么关联 ...WinForm多线程编程篇 ...我的多线程WinForm程序老是抛出InvalidOperationException ,怎么解决...
  • WinForm多线程

    2010-03-08 19:39:00
    但是由于一天要取20万左右的数据,后台只有一个线程运行,速度非常慢。 现在希望能用10个线程来从网页获取数据,该怎么实现呢? 希望各位前辈给以指点,刚接触线程,如果前辈能给个线程的框架出来,将不胜感激。
  • C# WinForm多线程

    2012-03-24 11:25:51
    Windows是一个任务的系统,如果你使用的是...而一个进程又是由线程所组成的,线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样...
  • 做了一个雷达显示程序,窗口线程按坐标绘制目标点,有一个后台线程更新目标的坐标。 运行起来发现过一会显示线程出现拖慢的想想,有卡顿。后来我把后台线程的处理函数改成一个 只有while(true);的死循环不做任何运算...
  • 【IT168技术】很多人问过我这样一个问题:WPF和以前的WinForm有什么区别? 我之前的回答一直是:没什么区别,仅仅是表示层用XAML封了层皮,使得Windows看起来更炫了。 今天(确切的说是昨天),我终于发现了我肤浅。...
  • 程序主窗体关闭后VS调试模式不退出,然后看任务管理器看到进程还在运行 直接使用代码在 主窗体的Formclosing...后来想到程序使用了多线程,因为主线程退出后其他线程仍在运行导致程序不会退出 将ThreadObj.IsBack...
  • c#winform多线程感想

    2018-07-20 14:22:00
    最近在做一个关于识别的项目,手动识别和自动识别,为了更好的保证自动识别不会引起界面的卡顿等现象,所以简单的学习了一下多线程,也只是入门但还是记录一下。 一、首先了解一下用多线程的理由 1、可以使用...
  • 可以想到,上次介绍的两个Timer基于ThreadPool,回调方法运行于不同于UI线程的新线程上,在这个方法中操作控件需要进行Invoke或BeginInvoke。其实,还有第三种System.Windows.Forms.Timer,它可以让回调...
  • 很多人问过这样一个问题:WPF和以前的WinForm有什么区别?  我之前的回答一直是:没什么区别,仅仅是表示层用XAML封了层皮,使得Windows看起来更炫了。  今天(确切的说是昨天),我终于发现了我肤浅。首先我要...
  • 转:WINFORM多线程编程

    2009-11-12 23:04:00
    把遇到过的对.Net线程的一些问题和误解集中起来和大家分享,也希望大家能一起补充,热烈欢迎讨论 目录 基础篇 ...前台线程与后台线程 ...异步和多线程有什么关联 ...WinForm多线程编程篇 ...
  • C# WinForm多线程开发(一) Thread类库

    千次阅读 2014-04-15 19:21:01
    原文地址: ...通过上叙代码,可以看到问题已经被解决了,通过等待异步,我们就不会总是持有主线程的控制,这样就可以在不发生跨线程调用异常的情况下完成多线程winform多线程控件的控制了。
  • 在我们应用程序开发过程中,经常会遇到一些问题,需要使用多线程技术来加以解决。本文就是通过几个示例程序给大家讲解一下多线程相关的一些主要问题。 执行长任务操作 许多种类的应用程序都需要长时间操作,比如:...
  • winform --线程

    2016-07-04 20:23:00
    线程:一个进程相当于一个公司,一个进程默认只有一个主线程;主线程主要控制窗体,如果你让他执行一段需要点时间的代码,那么窗体就没人...前台线程:默认,当所有前台线程全部运行完毕后,进程才会结束后台线程...
  • WinForm 多线程操作UI

    千次阅读 2016-11-28 09:54:41
    线程的winfom程序中,设置一个控件的值是很easy的事情,直接 this.TextBox1.value = "Hello World!";就搞定了,但是如果在一个新线程中这么做,比如: private void btnSet_Click(object sender, ...
  • WinForm 进程、线程

    2019-10-07 20:56:00
    进程是一个具有独立功能的程序关于某个数据集合的一次运行活动。 它可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体。 Process 类,用来操作进程。 命名空间:using System.Diagnostics; ...
  • WinForm 进程,线程

    2019-09-27 13:33:04
    进程是一个具有独立功能的程序关于某个数据集合的一次运行活动。 它可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体。 Process 类,用来操作进程。 命名空间:using System.Diagnostics; Process...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,992
精华内容 1,196
关键字:

winform后台多线程运行