c# 多线程与WINFORM 控件问题

c282174871c 2010-01-18 04:19:51
制作类似windows 更新 的更新程序
当在下载更新文件时 桌面右下角只出现更新程序图标
双击或下载完成后] 才跳出对话窗
我在 WINFORM 界面添加了一个notifyIcon1控件 和 progressBar1控件
progressBar1控件 是用来读取文件下载进度的
启动线程下载文件
开始时 progressBar1控件 报错 “线程间操作无效”
我在网上查了下 需要 要代理解决这个问题
private delegate void FlushClient(long offset, long fileTotalLength);//代理

private void Start_thread()
{
Thread thread = new Thread(new ThreadStart(DownloadFile2);
thread.IsBackground = true;
thread.Start();
}

public void DownloadFile2()
{
do
{
//将sleep和无限循环放在等待异步的外面
Thread.Sleep(1000);

ThreadFunction(offset, fileTotalLength);
}
while (true);
}
private void ThreadFunction(long offset , long fileTotalLength)
{
if (this.progressBar1.InvokeRequired)//等待异步
{
FlushClient fc = new FlushClient(ThreadFunction);
this.Invoke(fc);//通过代理调用刷新方法
}
else
{
this.progressBar1.Value = (int)(offset * 100 / fileTotalLength);
}
}
这样 改了后progressBar1控件 不报错了
可是 我 双击电脑桌面右下方 更新程序图标时 又 报“线程间操作无效”
这下我 可不行了
希望哪位高手来帮忙解决下
...全文
1217 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
snowkingdom 2010-01-18
  • 打赏
  • 举报
回复
技术还太浅
我们一直都用的CheckForIllegalCrossThreadCalls = false
龙宜坡 2010-01-18
  • 打赏
  • 举报
回复
最简单的一个例子:.NET WinForm中 一个 跨线程访问控件的示例

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace DelegateSample
{
/*********************************************************************
* 2009-10-29 guog,老鸟绕道!
* 跨线程控件访问示例:
* 因为.NET2.0以后禁止对控件跨线程访问,
* 所以可以使用委托来实现。
* 这是其中一种方法
*********************************************************************/
/// <summary>
/// 这里声明一个委托供线程调用
/// </summary>
/// <param name="txt"></param>
public delegate void AppendTextHandler(string txt);

public partial class Form1 : Form
{
Thread m_trd = null;
//实例化一个委托对象
AppendTextHandler m_handler = null;

public Form1()
{
InitializeComponent();
}

/// <summary>
/// 窗体Load 事件
/// </summary>
/// <param name="e"></param>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
//实例化一个委托对象
m_handler = new AppendTextHandler(AppendTextText);

//开启新线程
m_trd = new Thread(new ThreadStart(OtherThreadDoSomething));
m_trd.Start();
}

/// <summary>
/// 关闭窗体时结束创建的线程
/// </summary>
/// <param name="e"></param>
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
if (m_trd != null)
{
m_trd.Abort();
}
}

/// <summary>
/// 线程执行的方法
/// </summary>
private void OtherThreadDoSomething()
{
string _str;
while (Thread.CurrentThread.ThreadState!=ThreadState.Aborted)
{//线程未请求终止就一直执行
_str = System.Guid.NewGuid().ToString();
AppendTextText(_str);
Thread.Sleep(50);//可去掉
}
}

/// <summary>
/// 向当前窗体控件中增加文本
/// </summary>
/// <param name="txt"></param>
private void AppendTextText(string txt)
{
if (this.richTextBox1.InvokeRequired)
{//调用方在另外一个线程中
//在拥有此控件的线程上执行委托指向的方法
this.richTextBox1.Invoke(m_handler, txt);
}
else
{//调用方在当前线程中
this.richTextBox1.AppendText(txt + "\r\n");//增加文本
this.richTextBox1.ScrollToCaret();//滚动到当前目录
}
}
}
}
aofengdaxia 2010-01-18
  • 打赏
  • 举报
回复
Invoke
绝代坏坏 2010-01-18
  • 打赏
  • 举报
回复
Invoke
c282174871c 2010-01-18
  • 打赏
  • 举报
回复
在窗体load事件中。
System.Windows.Forms.Form.CheckForIllegalCrossThreadCalls = false;
试试吧。挺好用的。

这方法 我用了后 初始化窗体时 控件属性为 fales 运行程序在代码中改为 true 是没有反应的
要是为true 改成fales 可以 的
例如 初始化窗体时 button4.Enabled = false 时 在一个方法在 button4.Enabled = true 就改不过来了

如果 用委托的话那 双击方法 是怎么写委托的 能给个 例子吗
O15013245O 2010-01-18
  • 打赏
  • 举报
回复
public void DownloadFile2() 
{
do
{
//将sleep和无限循环放在等待异步的外面
Thread.Sleep(1000);

FlushClient fc = new FlushClient(ThreadFunction);
this.Invoke(fc,new object[]{offset, fileTotalLength});//
}
while (true);
}
四更山吐月 2010-01-18
  • 打赏
  • 举报
回复
非正规方法:
在窗体load事件中。
System.Windows.Forms.Form.CheckForIllegalCrossThreadCalls = false;
试试吧。挺好用的。


正规的方法就是使用委托,
所有子线程对控件的操作,都要委托给主线程。
huahua_asic 2010-01-18
  • 打赏
  • 举报
回复
更新程序图标的地方也要添加委托与Invoke的方法。
因为这里也会出现线程间操作无效、跨线程访问的异常~
huahua_asic 2010-01-18
  • 打赏
  • 举报
回复
更新程序图标的地方也要添加委托于Invoke的方法。因为这里也会出现线程间操作无效、跨线程访问的异常~
c282174871c 2010-01-18
  • 打赏
  • 举报
回复
我双击图标的 方法没有写在 线程里
只是 在线程运行的 情况下 双击图标
这也和线程有 冲突 ?
如果 我的线程 里有 多个控件 那是不是 真要写多个 委托
比如哦说 有个 button4 我想在 线程方法结束后 把他的 属性更改
如果放在线程外 线程方法没完成 button4 的属性 已经更改了
有什么好的方法吗 ? 大家多多帮忙
Neil198 2010-01-18
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 xray2005 的回复:]
更新程序图标

的地方也写成你上面的委托并Invoke的方式。
[/Quote]
正解,或者你更新图标不用线程
xray2005 2010-01-18
  • 打赏
  • 举报
回复
更新程序图标

的地方也写成你上面的委托并Invoke的方式。

110,546

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧