2

あなたが元気であることを願っています。

私はBeginInvokeで奇妙な問題に直面しています、そして私は本当にあなたの助けが必要です!

Reportタイプの複数のインスタンスを含むReportingクラスがあります

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はアクションを実行しません!レポートが作成されたスレッドがもう存在しないようなものです...

この問題を回避する方法について何かアイデアはありますか?

私がこの問題に直面しているのは今から1週間で、グーグルでスタックオーバーフローしました。しかし、何もありません!

どうもありがとう !

4

2 に答える 2

1

間違った呼び出しを使用していると思います。これを試してください:

if(this.InvokeRequired)
{
   this.Invoke(new Action<int,string>(GenerateReportAsImage), reportId, path);    
}
else
  ...
于 2010-01-22T18:18:03.303 に答える
0

以下は、ThreadPool.SetMinThreads ドキュメントからのものです。

アイドル スレッドは、スレッド プール スレッドの要求を満たすために必要な時間を短縮するために、スレッド プールによって維持されます。ワーカー スレッドと非同期 I/O スレッドには、個別の最小値が維持されます。システム リソースを節約するために、最小値を超えるアイドル スレッドは終了します。アイドル スレッドのメンテナンスはバックグラウンド タスクです。

また、私の理解では、BeginInvoke と Invoke は、コードの実際の呼び出しについて WinForms の「メッセージ ポンプ」に依存しています。それらがサービスで使用されているとは聞いたことがありません。メカニズムは、目に見える UI とメッセージ ポンプを備えた実際の WinForms アプリケーション用に設計されているようです。サービスで確実に動作させることは可能かもしれませんが、UserControl を作成して呼び出しを管理するスレッドに ThreadPool を使用するのではなく、少なくとも独自のスレッドを作成する必要があるようです。

BeginInvoke ではなく Invoke を使用する場合と使用しない場合があります。前者は同期、後者は非同期です。

于 2010-01-22T18:44:26.337 に答える