我正面临BeginInvoke的一个奇怪问题,我真的非常需要你的帮助!
我有一个类Reporting,其中包含多个Report
类型的实例Class Reporting : UserControl
{
//Reports are inherited from UserControl
Report _report1;
Report _report2;
Report _report3;
//Instanciate and return the Report corresponding to the passed ID (The report is
//instanciated and created only if it's null)
public Report GetReport(int reportId);
public delegate void GenerateReportAsImageDelegate(int reportId,string path)
//Generate the report and save it as image
public void GenerateReportAsImage(int reportId,string path)
{
if(InvokeRequired)
{
BeginInvoke(new GenerateReportAsImageDelegate(GenerateReportAsImage),new object[]{reportId,path});
}
else
{
//... Generating the report etc..
}
}
....
}
这是一个表单中显示的用户控件,同样的用户控件也可以从Windows服务中每分钟生成一次报告(并保存为图像)。
要每分钟生成一个报告,我正在使用System.Threading.Timer。
以下是我的类生成报告在服务中的样子:
class ReportServiceClass
{
Reporting _reportingObject;
System.Threading.Timer _timer;
Public ReportingServiceClass(int reportId)
{
_timer = new Timer(new TimerCallback(this.CreateReport), reportId, 0, 1000)
}
private void CreateReport(Object stateInfo)
{
int reportId = Convert.ToInt32(stateInfo);
//To ensure that the _reportingObject is created on the same thread as the report
if(_reportingObject == null)
_reportingObject = new _reportingObject();
_reportingObject.GenerateReportAsImage(reportId,@"c:\reports\report.PNG")
}
}
几乎所有东西都运行良好..有时CreateReport在ThreadPool的另一个线程中执行。因此,当我在报表及其组件(已在其他线程中创建)上执行某些操作时,InvokeRequired设置为true并且完全显而易见......但BeginInvoke不执行任何操作!它几乎就像创建报告的线程不再存在......
你们对如何避免这个问题有什么想法?
现在已经过了一个星期,我正面临着这个问题,我已经用Google搜索和堆栈溢出了。但没什么!
非常感谢!
答案 0 :(得分:1)
我认为你使用了错误的Invoke,试试这个:
if(this.InvokeRequired)
{
this.Invoke(new Action<int,string>(GenerateReportAsImage), reportId, path);
}
else
...
答案 1 :(得分:0)
以下内容来自ThreadPool.SetMinThreads文档:
空闲线程由线程池维护,以减少满足线程池线程请求所需的时间。为工作线程和异步I / O线程维护单独的最小值。空闲线程超过最小值终止,以节省系统资源。维护空闲线程是一项后台任务。
另外,我的理解是BeginInvoke和Invoke依赖于WinForms“消息泵”来实际调用你的代码。我从来没有听说过它们被用于服务中 - 似乎该机制是为具有可见UI和消息泵的真实WinForms应用程序而设计的。让它在服务中可靠地工作是可能的 - 但似乎你应该至少创建自己的线程而不是使用ThreadPool来创建UserControl并管理调用的线程。
您可能想要也可能不想使用Invoke而不是BeginInvoke。前者是同步的,后者是异步的。