BeginInvoke问题(委托不执行任何操作)

时间:2010-01-22 18:11:19

标签: c# invoke begininvoke

希望你很好。

我正面临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搜索和堆栈溢出了。但没什么!

非常感谢!

2 个答案:

答案 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。前者是同步的,后者是异步的。