我正在研究一些调用服务的代码。此服务调用可能会失败,如果确实如此,我希望系统再次尝试,直到它工作或经过太多时间。
我想知道我哪里出错了,因为下面的代码似乎没有正常工作......它随机只做一到四个循环......
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而不是......自从这样做以后我的问题就消失了,语义上我可以做同样的事情。谢谢你所有的帮助。
答案 0 :(得分:4)
我稍微修改了你的代码并且在10次迭代(VS 2008 Express)中没有遇到任何问题,这导致我:这是实际的代码,如果没有,是你吗?你确定已经发送了足够重现的问题吗?
如果我冒昧地猜测,我会说你发送它的数量不同count % 5 > 0
并且Logger.Fatal
会引发异常。
private void button1_Click(object sender, EventArgs e)
{
ProcessAsync("beer", 1);
}
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 - " + count.ToString(), e.Error);
else
this.Logger.Error("LOAD ERROR - The system can't load any data - " + count.ToString(), e.Error);
this.ProcessAsync(data, count);
}
}
};
worker.RunWorkerAsync();
}
SomeLogger Logger = new SomeLogger();
class SomeLogger
{
public void Fatal(string s, Exception e)
{
System.Diagnostics.Debug.WriteLine(s);
}
public void Error(string s, Exception e)
{
System.Diagnostics.Debug.WriteLine(s);
}
}
编辑:建议
对Logger.Fatal
的调用进行试试,看看会发生什么。
编辑:另一个建议
我怀疑你没有分享足够的代码供我们帮忙。这里成功的关键是在虚拟项目中隔离问题,该项目只有足够的代码来显示失败。我愿意打赌,如果你能做到这一点,你很可能不需要在这里发布这个问题......
你可以从我的假设开始,应该看到这很好用。然后开始将通用代码更改为您实际使用的内容(我将从Logger.Fatal的实际实现开始)。错误很可能在短时间内变得非常明显。
答案 1 :(得分:1)
这一定是我看到的最离奇的重试机制。你能做一个干净的吗?避免递归调用,除非它们简单易维护,因为它很容易导致错误。
答案 2 :(得分:1)
我没有看到明显的原因。但是,您的RunWorkerCompleted事件通常会在UI线程上运行。并挂起长达55秒。这是不可取的。
我没有任何理由可以想到你为什么不用try / catch块循环DoWork方法。
答案 3 :(得分:0)
有一件事真的是糟糕!
在RunWorkerCompleted()
Thread.Sleep()
内,您拨打Thread.Sleep()
。由于这个事实,这个函数将在你的应用程序将冻结的GUI线程中处理!
请勿在任何BackgroundWorker事件中调用{{1}},因为所有这些事件都将在GUI线程中处理。
所以这可能不是你当前问题的真正解决方案,但绝对是你应该关心的事情。
<强>更新强>
要在给定时间段后开始播放某些内容,您应该查看various timer classes。他们每个人都有自己的优点和缺点。要获得更深入的观点,您应该查看this article。