多线程遇到的问题与解决方案

多线程的两种方式:

1、线程池

  ThreadPool.QueueUserWorkItem(...);

  或者使用委托:  

  ParameterizedThreadStart start = new ParameterizedThreadStart(handleProtocol);
  start.BeginInvoke(pro, null, null);

2、自定义线程

  Thread myThead = new Thread(...);
  myThead.Start(...);

遇到的问题:

  使用线程池,在线程中创建WebBrowser对象时,会出现异常:“

  ActiveX control '8856f961-340a-11d0-a96b-00c04fd705a2' cannot be instantiated because the current...

  一种解决思路是使用自定义线程:

1   Thread myThead = new Thread(...);
2   myThead.SetApartmentState(ApartmentState.STA);
3   myThead.Start(...);

  该方案虽然可以正常创建WebBrowser,但控件的消息响应无法触发,即页面加载完成的处理程序无法执行(原因估计是线程设为单一线程)。

  一种解决思路是在主线程中创建WebBrowser对象,并将对象的引用传给开启的线程:

1   WebBrowser browser = new WebBrowser();
2   browser.Navigate(...); // 这步是必须的,否则会报异常:无法获取“WebBrowser”控件的窗口句柄。不支持无窗口的 ActiveX 控件。
3   Thread myThead = new Thread(...);  
4   myThead.Start(new object[]{browser});

  该方案在程序刚执行时正常,之后页面加载异常(但是程序仍在正常执行,原因未知)。

 一种解决思路是在主线程中创建WebBrowser对象,并使用线程池,所出现的问题如上一思路。

 可行的方案待研究...

 Thread.ApartmentState 默认值:MTA 

 Thread.IsBackground 默认值:false (即为前台线程)

 线程池中的线程为后台线程(backgournd thread)

跑批程序的两种多线程管理方式:

1、使用数组保存线程对象,之后Thread.Join方法等待线程结束,如下:

            Thread[] tds = new Thread[tmpThreadCount];
            while (tmpThreadCount >= 1)
            {
                Thread t = new Thread(new ThreadStart(ProcessTask));
                t.IsBackground = true;
                t.Start();
                tmpThreadCount--;
                tds[tmpThreadCount] = t;
            }

            for (int i = 0; i < tds.Length; i++)
            {
                tds[i].Join();
            }    
View Code

2、在类中添加字段,使用HashTable记录每个线程的状态,在线程内部更新和检查该表的状态,如线程都运行结束则在线程内部结束进程,如下:

主线程在等待状态:Console.ReadLine();

线程内部:

                //初始化线程状态
                htThreadStatus.Add(threadId, true);
                while(true)
                {
                    if(TaskQueue.Count > 0)
                   {...}
                    else
                    {
                             //队列为空时退出,并将该线程状态置为false
                            htThreadStatus[threadId] = false;
                            isComplete = true;
                            ICollection hashValues = htThreadStatus.Values;
                            foreach (bool bol in hashValues)
                            {
                                if (bol)
                                {
                                    isComplete = false;
                                    break;
                                }

                            }
                            if (isComplete)
                    System.Diagnostics.Process.GetCurrentProcess().Kill();
                            break;                           
                    }
                }                        
View Code
原文地址:https://www.cnblogs.com/MattCheng/p/4279534.html