关于IAsyncResult的问题

zhengqian529 2010-07-05 03:38:13
最近写了个程序,它可以批量处理文件,但是有一个问题一直没有得到解决,具体步骤如下:
1. Load 2000+ 文件
2. 运行
3. 运行到1000+左右,程序不动了,cpu占有率为0 (貌似一直处于线程等待状态,经过debug和测试以后,发现和文件没有关系,程序就是持续分析1000+文件之后就会静止,状态是运行状态,processbar依然动,cpu占用率为0)

然后我使用IAsyncResult

public delegate void AppDomainHandler(string[] sourceFilesToProcess, string[] rules, string logPath, string sourceFilter, string sourceFileName, string fileType, ref bool tempResult); //定义委托

AppDomainHandler appDomainMonitor = new OSLEBotRun().StartCheck; //将方法名StartCheck 赋值给委托类型


调用:

IAsyncResult ar = appDomainMonitor.BeginInvoke(sourceFiles, filteredRules,
logPath, sourceFilter, AppDomain.CurrentDomain.GetData("SourceFileName").ToString(),
fileType.ToString(), ref tempResult, null, null);
if (!ar.AsyncWaitHandle.WaitOne(TimeSpan.FromMinutes(5), false)) //防止程序静止,等待5分钟,如果5分钟线程没有返回,就返回false。
{
tempResult = false;
InvokeFailed = true;
//EndInvoke
appDomainMonitor.EndInvoke(ref tempResult, ar);
}

if (!InvokeFailed) //EndInvoke
appDomainMonitor.EndInvoke(ref tempResult, ar);


现在的问题是貌似下面这句不起作用,程序依然会自己静止不动:
if (!ar.AsyncWaitHandle.WaitOne(TimeSpan.FromMinutes(5), false))


我有哪个地方用错了吗? 希望能够有更好的方法解决这个问题。


...全文
279 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
tyg111 2010-07-15
  • 打赏
  • 举报
回复
学习了
zhengqian529 2010-07-06
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 amandag 的回复:]
参看下面的示例


C# code
using System;
using System.Threading;
using System.Diagnostics;

namespace ThreadDemo
{
class Program
{
//异步委托
static int OtherMethod(int data)
……
[/Quote]

程序会一直运行,我想要的是,过5分钟以后,当前AppDomain里面的程序就停止,然后卸载AppDomain并转移到下一个文件继续开启新的AppDomain继续运行。
如果不使用WaitHandle,是否可以使用Timer来界定这个时间呢?
zhengqian529 2010-07-06
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 amandag 的回复:]
如果真的超过了5分钟,楼主打算拿到的结果是什么?
[/Quote]
谢谢,我想得到的结果是,当过了5分钟,停止执行,忽略对当前文件的分析,开始分析下一个文件,
不知道你是否理解了?
不过貌似用这个等待句柄解决不了问题,因为它在一段时间之后,线程依然存在,也许我需要手动开启线程,然后在一段时间之后,调用Abort()方法来关闭线程,不知道是否能够达到目的。
zhengqian529 2010-07-06
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 ziliz854 的回复:]
不然的话,楼主使用一个bool变量作为异步操作结束的信号吧,在异步操作方法中去判断这个值,以便主线程能在需要的时候让该方法退出循环然后结束
[/Quote]
嗯,这个问题可能在这里讨论很抽象,我先把这个帖子结了,然后根据你的建议继续研究研究,StartCheck这个函数可能有问题,但是搞不懂问什么每次都是执行了1000多次以后,程序就静止了。所以想着是,只要它每次的运行超过5分钟(可以容忍5分钟,因为是在服务器上运行批量文件),就停止此次运行,转去运行下个文件。
ziliz854 2010-07-06
  • 打赏
  • 举报
回复
不然的话,楼主使用一个bool变量作为异步操作结束的信号吧,在异步操作方法中去判断这个值,以便主线程能在需要的时候让该方法退出循环然后结束
ziliz854 2010-07-06
  • 打赏
  • 举报
回复
试了9楼的例子后发现被楼主误导了:
现在的问题是貌似下面这句不起作用,程序依然会自己静止不动:
C# codeif (!ar.AsyncWaitHandle.WaitOne(TimeSpan.FromMinutes(5), false))

MSDN说明:异步调用,通过使用 BeginInvoke 方法。BeginInvoke 启动进程然后立即返回。使用 EndInvoke 一直等到 BeginInvoke 所启动的进程完成为止
也就是说,AsyncWaitHandle.WaitOne等待了5分钟,异步操作还没有结束,于是返回false,但楼主代码中拿到false后又调用了EndInvoke方法,本意是想让异步操作结束,实际的效果相当于是一个没有时间限制的Wait,所以程序一直运行下去。如果此时暂停执行的话,主线程应该是停在EndInvoke上。

建议楼主查查StartCheck方法,因为只要该方法运行结束的话,EndInvoke也能得到返回值的,如果说程序一直停不下来,还是改改StartCheck方法吧。
“过5分钟以后,当前AppDomain里面的程序就停止,然后卸载AppDomain并转移到下一个文件继续开启新的AppDomain继续运行”这样做的话,即使开启了新的AppDomain,也是会出现和前一次一样的结果的(就是程序一直运行)。
amandag 2010-07-05
  • 打赏
  • 举报
回复
参看下面的示例

using System;
using System.Threading;
using System.Diagnostics;

namespace ThreadDemo
{
class Program
{
//异步委托
static int OtherMethod(int data)
{
Console.WriteLine("OtherMethod Started");
while(true)
{
++data;
Console.Write(data + " ");
if (data > 1000)
{
data = 0;
}
if (data > 1001)
{
break;
}
}
Console.WriteLine("OtherMethod Completed");
return data;
}
public delegate int AsyncDelegate(int data);
static void Main()
{
AsyncDelegate ad = OtherMethod;
IAsyncResult ar = ad.BeginInvoke(1, null, null);

if (!ar.AsyncWaitHandle.WaitOne(3 * 1000, false))
{
Console.WriteLine("Can't get the result now");
}

//int result = ad.EndInvoke(ar);
//Console.WriteLine("result:{0}", result);
}
}
}


最后两行注释后,程序在过3分钟会结束;楼主去掉注释再执行下看看
amandag 2010-07-05
  • 打赏
  • 举报
回复
如果真的超过了5分钟,楼主打算拿到的结果是什么?
zhengqian529 2010-07-05
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 ziliz854 的回复:]
那还真搞不懂了,你让程序运行,过5分钟以后还没响应的话再用VisualStudio暂停,看一下各个线程分别在哪行代码上吧,不调试弄不明白啊~~~
[/Quote]
我试着弄弄看,先谢谢了 :)
ziliz854 2010-07-05
  • 打赏
  • 举报
回复
那还真搞不懂了,你让程序运行,过5分钟以后还没响应的话再用VisualStudio暂停,看一下各个线程分别在哪行代码上吧,不调试弄不明白啊~~~
zhengqian529 2010-07-05
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 ziliz854 的回复:]
WaitHandle.WaitOne 方法阻止当前线程,直到当前的 WaitHandle 收到信号。
如果线程异常了,应该是不会返回false的,直到指定的5分钟之后才返回false
[/Quote]
我的那个程序就是停在那就不动了,完全超过5分钟了,应该是没有返回false,因为如果返回false,我会获取到然后立刻调用EndInvoke()方法,但是貌似没有按照预想的那么处理。
ziliz854 2010-07-05
  • 打赏
  • 举报
回复
WaitHandle.WaitOne 方法阻止当前线程,直到当前的 WaitHandle 收到信号。
如果线程异常了,应该是不会返回false的,直到指定的5分钟之后才返回false
zhengqian529 2010-07-05
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 ziliz854 的回复:]
看不出问题,还是Debug看看异步调用的那个方法在执行什么代码还是说那个线程异常了之类的~~
[/Quote]

如果线程在执行过程中异常了,会不会返回false? 不会返回吗?
ziliz854 2010-07-05
  • 打赏
  • 举报
回复
看不出问题,还是Debug看看异步调用的那个方法在执行什么代码还是说那个线程异常了之类的~~

17,740

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 .NET Framework
社区管理员
  • .NET Framework社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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