首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

c# 多线程编程,该如何处理

2012-09-20 
c# 多线程编程今天看委托的同步与异步调用,看的我蛋好痛。。。首先是:Control的Invoke和BeginInvoke与Delegat

c# 多线程编程
今天看委托的同步与异步调用,看的我蛋好痛。。。

首先是:Control的Invoke和BeginInvoke与Delegate的Invoke和BeginInvoke是不同的? 这个我首先就没怎么理解。

其实看那个工作线程同步更新UI,看的闷,感觉似懂,非懂。

还看到一段话非常有道理,但具体不知道怎么体现到程序里。这段话是这样的

“用工作线程去更新界面,在多线程中直接调用界面控件的方法是错误的,正确的做法是将工作线程中涉及到更新界面
的代码封装起来,通过invoke或者begin invoke来调用。(这里在代码里就不懂怎么实现了。)两者的区别就是一个导致工作线程等待,一个则不会。

有哪位好心的老大帮忙解释下吧。。。最好弄个例子。。。或者我发个例子。。。

using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace WindowsApplication4
{
  /**/
  /// <summary>
  /// gui 类
  /// </summary>
  public partial class Form1 : Form
  {
  public Form1()
  {
  InitializeComponent();
  }
  private void button1_Click(object sender, EventArgs e)
  {
  //用子线程工作
  new System.Threading.Thread(new System.Threading.ThreadStart(StartDownload)).Start();
  }

  //开始下载
  public void StartDownload()
  {
  Downloader downloader = new Downloader();
  downloader.onDownLoadProgress += new Downloader.dDownloadProgress(downloader_onDownLoadProgress);
  downloader.Start();
  }
  //同步更新ui
  void downloader_onDownLoadProgress(long total, long current)
  {
  if (this.InvokeRequired)
  {
  this.Invoke(new Downloader.dDownloadProgress(downloader_onDownLoadProgress), new object[] { total, current });
  }
  else
  {
  this.progressBar1.Maximum = (int)total;
  this.progressBar1.Value = (int)current;
  }
  }
  } //重点是这段,

  /**/
  /// <summary>
  /// 下载类
  /// </summary>
  public class Downloader
  {
  //委托
  public delegate void dDownloadProgress(long total, long current);
  //事件
  public event dDownloadProgress onDownLoadProgress;
  //开始模拟工作
  public void Start()
  {
  for (int i = 0; i < 100; i++)
  {
  if (onDownLoadProgress != null)
  onDownLoadProgress(100, i);
  System.Threading.Thread.Sleep(100);
  }
  }
  }
}

我不能再看了,头要爆炸了。明天来看看各位的回复、、、另外我没分了。。不好意思,就30了。。。

[解决办法]

C# code
        private void button1_Click(object sender, EventArgs e)        {            Thread t = new Thread(new ThreadStart(ThreadMethod));            t.Start();        }        void ThreadMethod()        {            label1.Text = "从非UI线程中修改。。";// 在这里会异常。。            // 线程间操作无效: 从不是创建控件“label1”的线程访问它。。        }
[解决办法]
Invoke就是直接运行,BeginInvoke是开启另一个辅助线程运行
调用Invoke是利用反射在执行
Delegate的BeginInvoke是在新的线程执行的,Control.BeginInvoke是在创建Control的线程里执行的
[解决办法]
C#托管的执行的代码都是单线程的,不过可以在执行过程中(或是有程序有需要的时候)可以附加线程来完成工作
[解决办法]
invoke就是调用的意思
Control的Invoke和BeginInvoke 一般是在非创建控件的进程中使用,以调用和控件操作有关的方法,你先看看多线程吧
[解决办法]
这个我正在做,可以给你点提示:


首先定义变量public static Form1 from;
在你调用方法类Downloader里面也设置一个变量Form1 mainform;
且构造函数为:
public override void init(Form1 from)
{
this.mainform = from;
}
启动调用线程的时候给方法类赋值
Downloader.init(form);
下面的泪一定要写在主form里
public void UpdateMessageList(string msg)
{

BeginInvoke(new myDelegate(delegate()
{
/** if (listBoxMsg.Items.Count > 100)
{
listBoxMsg.Items.RemoveAt(0);
}*/
//listBoxMsg.SelectedIndex = listBoxMsg.Items.Add(msg);
textBox1.Text +=msg;
this.textBox1.Focus();//获取焦点
this.textBox1.Select(this.textBox1.TextLength, 0);//光标定位到文本最后
this.textBox1.ScrollToCaret();//滚动到光标处
})); 
}

在执行线程里调用
 this.mainform.UpdateMessageList(string);就能实现,且不会报错
[解决办法]
一个简单的例子

C# code
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Threading;namespace doWorker{    public partial class Form1 : Form    {        delegate void MyDelegate(int value);        Thread t;        int i = 0;        public Form1()        {            InitializeComponent();        }        // 在新的线程中做“需要长时间做的”工作        private void button1_Click(object sender, EventArgs e)        {            t = new Thread(doWork);            t.Start();        }        // 要长时间做的工作        void doWork()        {            MyDelegate d = new MyDelegate(setValue);            while (true)            {                ++i;                this.Invoke(d, i);                Thread.Sleep(100);            }        }        // 更新用户界面        void setValue(int value)            {            label1.Text = value.ToString();        }        // 终止线程的执行        private void button2_Click(object sender, EventArgs e)        {            t.Abort();        }    }} 

热点排行