2011-12-13 12 views
2

job.Delegate.EndInvoke()を呼び出すと、「System.Delegate」に「EndInvoke」の定義が含まれていないというVisual Studio 2010が表示されるのはなぜですか?どうすれば修正できますか? BeginInvoke()が好きで、BeginInvoke()の直後にEndInvoke()を追加しても文句を言っていないことに注意してください。"System.Delegate"に 'EndInvoke'の定義が含まれていないというVisual Studio 2010が表示されるのはなぜですか?

私は、バックアップジョブを追跡するために少しJobTrackerクラスを持っている:

public class JobTracker 
{ 
    private class Job 
    { 
     public Account Account { get; set; } 
     public IAsyncResult Result { get; set; } 
     public Delegate Delegate { get; set; } 
     public bool IsCompleted { get { return result.IsCompleted } } 
     public string Instance { get { return Account.Instance } } 
    } 

    public List<Job> Running = new List<Job>; 

    public void AddJob(Account a, IAsyncResult result, Delegate del) 
    { 
     var j = new Job { Account = a, Result = result, Delegate = del }; 
     Running.Add(j); 
    } 

    public void RemoveJob(Job job) 
    { 
     Running.Remove(job); 
    } 

public bool IsInstanceRunning(string instance) 
{ 
    return (Running.Count(x => x.Instance == instance) > 0); 
} 
} 

これらのバックアップジョブは、BeginInvokeを()/ EndInvokeを()を介して非同期に発生します。呼び出しコード(簡略化)は次のようになります。

public void BackupAccounts(IEnumerable<Account> accounts, int maxconcurrent = 4) 
{ 
    // local copy 
    List<Accounts> myaccounts = accounts.ToList(); 
    var jobs = new JobTracker(); 

    while (myaccounts.Count > 0) 
    { 
     // check our running jobs 
     foreach (var job in jobs.Running) 
     { 
      if (job.IsCompleted) 
      { 
// PROBLEM LINE: 
       job.Delegate.EndInvoke(); 
       jobs.RemoveJob(job); 

      } 
     } 

     // more jobs! 
     while (jobs.Count < maxconcurrent) 
     { 
      int i = 0; 
      Account account = null; 

      // choose the next account on a free instance 
      while (int < accounts.Count) 
      { 
       account = accounts[i]; 
       // instance in use? 
       if (jobs.InstanceIsRunning(account.Instance)) 
       { 
        i += 1; 
        continue; 
       } 
       else 
       { 
        // start the job 
        accounts.RemoveAt(i); 
        BackupDelegate del = new BackupDelegate(BackupAccount, account); 
        IAsyncResult result = del.BeginInvoke(); 
        jobs.AddJob(account, result, del); 
       } 
      } 
     } 

     // we're all full up, give it some time to work 
     Thread.Sleep(2000); 
    } 
} 

PS - このコードは大幅に簡略化できます。それは最初の、それを稼働させる反復です - 私はVSがそれを好まない理由を理解できません。あなたがBeginInvokeを呼び出すと

答えて

5

、あなたはDelegate特定サブクラスでそれを呼んでいます。 EndInvokeに電話すると、System.Delegateに電話をかけようとしていますが、これは機能しません。各サブクラスは、独自のInvoke/BeginInvoke/EndInvokeのメソッドセットを宣言します。これは、メソッドのシグネチャが、あなたが話しているデリゲートタイプのシグネチャによって異なることを前提としています。 documentation for System.Delegateを見ると、それらの方法はありません。

あなたのコードが達成しようとしていることは本当に明確ではありませんが、EndInvokeに電話する場合は、Job.Delegateを特定の委任タイプにする必要があります。

+0

私は定義を含んでいませんでしたが、Delegateのサブクラスでこれを呼び出すことに気づくでしょう。 「//ジョブを開始する」の下で、BackupDelegateをインスタンス化し、JobTracker.AddJob()に送信します。私は誤解していますか? –

+0

@ sh-beta:はい、あなたは '' Job.Delegate'のコンパイル時の型を見ています - それはちょうど 'Delegate'です。ですから、 'job.Delegate.EndInvoke()'を呼び出すと、 'Delegate'で宣言された' EndInvoke'メソッドを見つけようとしています。 'BackupDelegate'ではそうではありません。なぜなら、 'BeginInvoke'呼び出しはうまくコンパイルされます。なぜなら、' del'のコンパイル時の型は 'BackupDelegate'です。 –

+0

ああ、私は今参照してください。ありがとう! –

3

EndInvokeDelegateに存在しないためです。代わりに、ジョブクラスにBackupDelegateへの参照を保持させる必要があります。

関連する問題