后台工作人员行为异常
我正在编写一些调用服务的代码。此服务调用可能会失败,如果确实如此,我希望系统重试,直到它正常工作或已经过去了太多时间。
我想知道我哪里出了问题,因为以下代码似乎无法正常工作...它随机只执行一到四个循环...
protected virtual void ProcessAsync(object data, int count)
{
var worker = new BackgroundWorker();
worker.DoWork += (sender, e) =>
{
throw new InvalidOperationException("oh shiznit!");
};
worker.RunWorkerCompleted += (sender, e) =>
{
//If an error occurs we need to tell the data about it
if (e.Error != null)
{
count++;
System.Threading.Thread.Sleep(count * 5000);
if (count <= 10)
{
if (count % 5 == 0)
this.Logger.Fatal("LOAD ERROR - The system can't load any data", e.Error);
else
this.Logger.Error("LOAD ERROR - The system can't load any data", e.Error);
this.ProcessAsync(data, count);
}
}
};
worker.RunWorkerAsync();
}
干杯 安东尼
更新:
我已经将代码切换为使用 ThreadPool.QueueUserWorkItem 来代替...自从这样做以来,我的问题就消失了,从语义上讲我可以做同样的事情。感谢你们所有的帮助。
I'm working on some code that calls a service. This service call could fail and if it does I want the system to try again until it works or too much time has passed.
I am wondering where I am going wrong as the following code doesn't seem to be working correctly... It randomly only does one to four loops...
protected virtual void ProcessAsync(object data, int count)
{
var worker = new BackgroundWorker();
worker.DoWork += (sender, e) =>
{
throw new InvalidOperationException("oh shiznit!");
};
worker.RunWorkerCompleted += (sender, e) =>
{
//If an error occurs we need to tell the data about it
if (e.Error != null)
{
count++;
System.Threading.Thread.Sleep(count * 5000);
if (count <= 10)
{
if (count % 5 == 0)
this.Logger.Fatal("LOAD ERROR - The system can't load any data", e.Error);
else
this.Logger.Error("LOAD ERROR - The system can't load any data", e.Error);
this.ProcessAsync(data, count);
}
}
};
worker.RunWorkerAsync();
}
Cheers
Anthony
UPDATE:
I've switched my code over to use ThreadPool.QueueUserWorkItem instead... Since doing this my problems have gone away and semantically I can do the same thing. Thanks for all your help guys.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我稍微修改了您的代码,并且在 10 次迭代(VS 2008 Express)中没有遇到任何问题,这使我想到:这是实际代码吗?如果不是,您确定吗?已发送足够的信息来重现该问题?
如果我大胆猜测,我会说您发送的计数会有所不同,例如
count % 5 > > 0
并且在Logger.Fatal
中抛出异常。编辑:建议
在对 Logger.Fatal 的调用周围放置一个 try-catch 并看看会发生什么。
编辑:另一个建议
我怀疑您没有分享足够的代码来帮助我们。这里成功的关键是将问题隔离在一个只有足够代码来显示失败的虚拟项目中。我愿意打赌,如果你能做到这一点,你很可能不需要将其作为问题发布在这里......
你可以从我的假设开始,并且应该看到这工作得很好。然后开始将通用代码更改为您实际使用的代码(我将从 Logger.Fatal 的实际实现开始)。该错误可能会在短时间内变得非常明显。
I've modified your code slightly and don't have any issues running through 10 iterations (VS 2008 Express) which leads me to this: Is this the actual code and if not, are you sure you've sent enough to reproduce the issue?
If I were to venture a guess, I would say that the count you're sending it varies such that
count % 5 > 0
and that there's an exception getting thrown inLogger.Fatal
.EDIT: A Suggestion
Put a try-catch around the call to
Logger.Fatal
and see what happens.EDIT: Another suggestion
I suspect you aren't sharing enough code for us to help. The key to success here would be to isolate the problem in a dummy project that only has enough code to show the failure. I'd be willing to bet that if you can do that, you most likely wouldn't need to post this as question here...
You can start with my assumptions and should see that this works just fine. Then start changing the generalized code into what you're actually using (I'd start with the real implementation of Logger.Fatal). The error will likely become pretty obvious in short order.
这一定是我见过的最奇怪的重试机制了。你能做一个更干净的吗?避免递归调用,除非它们简单且易于维护,因为它很容易导致错误。
This must be the most bizarre retry mechanism I saw. Can you make a cleaner one? Avoid recursive calls unless they are simple and easy to maintain, because it can easily lead to mistakes.
我没有看到明显的原因。但是,您的 RunWorkerCompleted 事件通常会在 UI 线程上运行。并悬挂长达55秒。那是不可取的。
我无法想象为什么您不使用 try/catch 块在 DoWork 方法中循环。
I don't see an obvious reason. However, your RunWorkerCompleted event would normally run on the UI thread. And hang it for as long as 55 seconds. That cannot be desirable.
There isn't any reason I can think of why you'd not just loop in the DoWork method with a try/catch block.
有件事真的糟糕!
在
RunWorkerCompleted()
中,您调用Thread.Sleep()
。事实上,该函数将在 GUI 线程中处理,您的应用程序将冻结!请不要在BackgroundWorker 的任何事件中调用
Thread.Sleep()
,因为所有这些事件都将在GUI 线程内处理。因此,这可能不是您当前问题的真正解决方案,但绝对是您应该关心的事情。
更新
要在给定时间段后开始某些操作,您应该查看 各种 计时器 < a href="http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx" rel="nofollow noreferrer">类。他们每个人都有自己的优点和缺点。要获得更深入的了解,您应该查看这篇文章。
There is one thing that is really bad!
Within your
RunWorkerCompleted()
you call aThread.Sleep()
. Due to the fact, that this function will be processed within the GUI thread your application is going to freeze!Please don't call
Thread.Sleep()
within any event of the BackgroundWorker cause all of them will be processed within the GUI thread.So this is maybe not a real solution to your current problem, but definitely something you should care about.
Update
To start something after a given time period you should take a look into the various timer classes. Each of them has it's own pros and cons. For a more insight view you should take a look into this article.