C# 行为古怪的幕后工作者
我正在编写一些调用服务的代码。此服务调用可能会失败,如果失败,我希望系统重试,直到它正常工作或时间过长为止 我想知道我哪里出错了,因为下面的代码似乎工作不正常。。。它随机只做一到四个循环C# 行为古怪的幕后工作者,c#,.net,multithreading,backgroundworker,long-running-processes,C#,.net,Multithreading,Backgroundworker,Long Running Processes,我正在编写一些调用服务的代码。此服务调用可能会失败,如果失败,我希望系统重试,直到它正常工作或时间过长为止 我想知道我哪里出错了,因为下面的代码似乎工作不正常。。。它随机只做一到四个循环 protected virtual void ProcessAsync(object data, int count) { var worker = new BackgroundWorker(); worker.DoWork += (sender, e) => {
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();
}
受保护的虚拟void ProcessAsync(对象数据,整数计数)
{
var worker=新的BackgroundWorker();
worker.DoWork+=(发件人,e)=>
{
抛出新的InvalidOperationException(“哦,shiznit!”);
};
worker.RunWorkerCompleted+=(发件人,e)=>
{
//如果发生错误,我们需要告诉数据
如果(例如错误!=null)
{
计数++;
系统.线程.线程.睡眠(计数*5000);
如果(count这一定是我见过的最奇怪的重试机制。你能做一个更干净的吗?除非递归调用简单且易于维护,否则避免递归调用,因为它很容易导致错误。这一定是我见过的最奇怪的重试机制。你能做一个更干净的吗?除非递归调用简单且易于维护,否则避免递归调用n、 因为它很容易导致错误。我稍微修改了您的代码,在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);
}
}
private void按钮1\u单击(对象发送者,事件参数e)
{
ProcessAsync(“啤酒”,1);
}
受保护的虚拟void ProcessAsync(对象数据,int计数)
{
var worker=新的BackgroundWorker();
worker.DoWork+=(发件人,e)=>
{
抛出新的InvalidOperationException(“哦,shiznit!”);
};
worker.RunWorkerCompleted+=(发件人,e)=>
{
//如果发生错误,我们需要告诉数据
如果(例如错误!=null)
{
计数++;
//系统.线程.线程.睡眠(计数*5000);
如果(count我稍微修改了您的代码,并且在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);
}
}
private void按钮1\u单击(对象发送者,事件参数e)
{
ProcessAsync(“啤酒”,1);
}
受保护的虚拟void ProcessAsync(对象数据,int计数)
{
var worker=新的BackgroundWorker();
worker.DoWork+=(发件人,e)=>
{
抛出新的InvalidOperationException(“哦,shiznit!”);
};
worker.RunWorkerCompleted+=(发件人,e)=>
{
//如果发生错误,我们需要告诉数据
如果(例如错误!=null)
{
计数++;
//系统.线程.线程.睡眠(计数*5000);
如果(count我看不出明显的原因。但是,您的RunWorkerCompleted事件通常会在UI线程上运行。并将其挂起长达55秒。这是不可取的
我想不出为什么你不使用try/catch块循环DoWork方法。我看不出明显的原因。但是,你的RunWorkerCompleted事件通常会在UI线程上运行。并将其挂起55秒。这是不可取的
我想不出有什么理由不使用try/catch块来循环DoWork方法。有一件事非常不好
在RunWorkerCompleted()
中调用Thread.Sleep()
。由于该函数将在GUI线程中处理,因此应用程序将冻结
请不要在BackgroundWorker的任何事件中调用Thread.Sleep()
,因为它们都将在GUI线程中处理
所以这可能不是你当前问题的真正解决方案,但肯定是你应该关心的事情
更新
要在给定的时间段后开始某件事,你应该看一看。每一个都有它自己的优点和缺点。要获得更深入的见解,你应该看一看。有一件事是非常不好的。
在RunWorkerCompleted()
中调用Thread.Sleep()
。由于该函数将在GUI线程中处理,因此应用程序将冻结
请不要在BackgroundWorker的任何事件中调用Thread.Sleep()
,因为它们都将在GUI线程中处理
所以这可能不是你当前问题的真正解决方案,但肯定是你应该关心的事情
更新
若要在给定的时间段后开始某项工作,您应该查看。它们每个都有各自的优点和缺点。若要查看更深入的视图,您应该查看。它是否与worker.RunWorkerAsync();
而不是this.ProcessAsync(数据,计数)一起工作
?@Marc Gravell:如果是这样的话,我想他必须使用一个全局计数器。我能让这段代码像你描述的那样失败的唯一方法是将计数从1到4(包括1)随机开始有了<代码>日志。失败< /代码>抛出一个异常。服务是一个WCF服务吗?如果你有控制权的话,那么如果考虑WCF可靠的会话。它不会与<代码> Works.RunWorksActhCy](<代码> >而不是<代码> >吗?
?@Marc Gravell:那样的话,我想,他就得用一个全局计数器了。这是我唯一能做到的