一个关于异步调用+多线程+异常处理的问题,请高手帮忙!!!

isaacyh 2004-12-15 09:56:26
我在WinForm里加了如下引用:
using System.Threading;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
using System.Reflection;
using System.Runtime.CompilerServices;

声明了以下变量:

private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Button button1;
private int count = 0;
private delegate void AddMessageHandler(string msg);
private AddMessageHandler addMsgHandler;
private AsyncCallback addCallback;
private System.Windows.Forms.Timer timer1;//timer1的时间间隔是一秒

private System.ComponentModel.IContainer components;

private string[] hehe = new string[3]{"first","second","third"};

定义了如下方法:

public Form1()
{
InitializeComponent();
//指定代理调用的方法
addMsgHandler = new AddMessageHandler(AddMsg);
//指定回调的方法
addCallback = new AsyncCallback(EndMsg);
}

private void button1_Click(object sender, System.EventArgs e)
{
this.count = 0;
//timer启动一个线程
this.timer1.Start();
}

private void add(object hehe)
{
this.timer1.Stop();
string[] thishehe = (string[])hehe;
try
{
this.timer1.Start();
IAsyncResult ar = addMsgHandler.BeginInvoke(thishehe[count],addCallback,null);
}
catch(IndexOutOfRangeException E) //获得异常
{
Console.WriteLine("exception at :{0},{1}",DateTime.Now.Ticks,count);
this.timer1.Stop();
IAsyncResult ar = addMsgHandler.BeginInvoke(E.Message,addCallback,null);
}
count++;
}

private void AddMsg(string msg)
{
this.textBox1.Text = msg;
}

private void EndMsg(IAsyncResult ar)
{
AddMessageHandler tempMessageHandler = (AddMessageHandler)((AsyncResult)ar).AsyncDelegate;
Console.WriteLine(DateTime.Now);
tempMessageHandler.EndInvoke(ar);
}

private void timer1_Tick(object sender, System.EventArgs e)
{
//timer1的时间间隔是一秒
this.add(this.hehe);
}

由于程序是多线程的,又是异步调用的,所以timer1_Tick触发的方法改变this.textBox1的text是不会受到后台的影响的,但程序运行结果不是这样:

在显示first和second时的确可以随意拖动WinForm,程序不受后台处理的影响,可以证明是异步的,
但当catch(IndexOutOfRangeException E)获得异常时,即显示third后WinForm窗体不能拖动,有同步执行的感觉,感觉是等处理完了IndexOutOfRangeException E才回到WinForm,查看输出,发现这时加载了已加载“c:\winnt\assembly\gac\mscorlib.resources\1.0.5000.0_zh-chs_b77a5c561934e089\mscorlib.resources.dll”,未加载符号。
我是Win2000Server的系统
查c:\winnt\assembly\下的确有mscorlib.resources这个程序集的映射,但找不到mscorlib.resources.dll

想利用mscorlib.dll里的Assembly.Load方法来自己加载这个程序集,但是失败,望高手指点为什么会出现这样的情况?
是由于程序在load mscorlib.resources时所有的线程都会挂起等待吗????

有什么解决办法呢?
...全文
815 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
layershow 2004-12-19
  • 打赏
  • 举报
回复
Forms.Timer 中出现的异常确实会轻微阻断Form的运行,
说轻微是因为它不是真正的在单独线程内运行
这种时间上的差距可以被操作用户所忽略

但是楼主所遇到的问题不是因为它引起的,应该是因为IDE环境调试的介入
为了方便你开发,IDE针对进程所有使用到的资源都会调试,
可能应该说是"尝试去调试"
任何用户启用的线程出现问题都会被IDE截获,会提示你出现异常
实际上呢,运行时用户启用的线程中未被捕获的异常都会被 "忽略"

不会因为一个异常处理耗时这么多的,呵呵,不用担心
至于IDE是怎么去做调试工作的,这个我也不了解:)
这些东西在开发的时候就不要顾虑这么多了
用Ctrl + F5 运行试试,这个不执行调试
The123 2004-12-18
  • 打赏
  • 举报
回复
我没讲清楚。
你的thishehe是你form线程上的资源,出了异常,自然要中断form线程。
你单独定义一个class,把你想要操作的数组放到那个class里试试.
isaacyh 2004-12-18
  • 打赏
  • 举报
回复
其实,用其它的两种Timer我都试过,效果还是一样的,不信你们runrun代码!
The123 2004-12-18
  • 打赏
  • 举报
回复
Sunmast(速马|Reloading...) 的资源很OK了.

异常处理会中止引发异常的线程,你的timer1的线程和你form1的线程是同一个线程。
http://msdn.microsoft.com/msdnmag/issues/04/02/TimersinNET/default.aspx

异常发生在这里,调用这段代码的是调用add方法的线程,也就是你的timer1的线程。
IAsyncResult ar = addMsgHandler.BeginInvoke(thishehe[count],addCallback,null);
所以 “即显示third后WinForm窗体不能拖动”,因为"显示third后"异常发生了。

既然中止了form1的线程那为什么异常后又能恢复呢?
http://blog.sunmast.com/sunmast/archive/2004/12/06/1043.aspx

"......未加载符号"应该指的是一些和调试相关的信息,就是一些和编译调试相关的参数了,和你出现的问题无关,如果你想获得详细的编译调试信息,可以打开相关的参数,你可以去MSDN上搜搜,那里应该有的。
isaacyh 2004-12-17
  • 打赏
  • 举报
回复
还好了,这只是一个模型,真正到项目里后台可能有好几个控制线程在运行,它们都要异步的与上层进行交互的!
nga96 2004-12-17
  • 打赏
  • 举报
回复
兄弟也够复杂吧,不会
isaacyh 2004-12-17
  • 打赏
  • 举报
回复
是不是分不够亚,可以加的!
只要解决了,还可以加200分!
wangsaokui 2004-12-17
  • 打赏
  • 举报
回复
private void button1_Click(object sender, System.EventArgs e)
{
this.count = 0;
//timer启动一个线程
new Thread(new ThreadStart(custome_time)).Start();
}

private void custome_time()
{
while(true)
{
add(this.hehe);
Thread.Sleep(1000);
}
}

see:
http://dev.csdn.net/develop/article/29/29874.shtm
其中第二种方法比较适合你
速马 2004-12-17
  • 打赏
  • 举报
回复
System.Windows.Forms.Timer不是多线程的,而是直接在主线程操作
这里有三种Timer的区别:
http://blog.joycode.com/yaodong/articles/25845.aspx

在别的线程操作窗体,必须使用Control.Invoke(someDelegate)方法
否则会出现怪异情况(Windows控件不是线程安全的)

Windows窗体的异常处理,看这个post:
http://blog.sunmast.com/sunmast/archive/2004/12/06/1043.aspx
herony420 2004-12-17
  • 打赏
  • 举报
回复
你可以将add方法的执行重新使用一个新的委托,然后异步执行委托,让这个异步执行的委托调用这个add
gxsun 2004-12-16
  • 打赏
  • 举报
回复
up
isaacyh 2004-12-16
  • 打赏
  • 举报
回复
大家帮帮我亚,走过的路过的也帮我顶顶呀!

虽然可以在FormLoad方法里先throw个IndexOutOfRangeException E,让程序自己加载,但这总不是个办法啊,要是在其他线程里由有其他的程序集要加载,我怎么办呢?
mobydick 2004-12-16
  • 打赏
  • 举报
回复
不擅长多线程和异步调用的问题。
mark
isaacyh 2004-12-16
  • 打赏
  • 举报
回复
大家给个主意亚!
ranzy 2004-12-16
  • 打赏
  • 举报
回复
mark
yuqingjiang 2004-12-16
  • 打赏
  • 举报
回复
同关注装配件的问题.
isaacyh 2004-12-16
  • 打赏
  • 举报
回复
自己up一下
isaacyh 2004-12-16
  • 打赏
  • 举报
回复
那有没有什么解决的办法呢?
难道只有等它回来??
那异步还有什么意义亚?
sunyou 2004-12-16
  • 打赏
  • 举报
回复
进入异常处理这个特殊步骤时,用户的程序是被挂起的,如果有针对该异常的用户异常处理程序,则调用这个异常处理程序,直到异常处理结束才回到用户的正常程序中。没有异常处理程序则Dotnet使用默认处理-弹一个对话框“没有处理的异常...”。
isaacyh 2004-12-16
  • 打赏
  • 举报
回复
但只要mscorlib.resources.dll被加载过了,就不会出现这个问题。
而且,按道理说这个异常应该是后台进程去处理亚,为什么整个程序会停止呢?
加载更多回复(4)

110,499

社区成员

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

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

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