Why is Visual Studio 2010 telling me “‘System.Delegate’ does not contain a definition for ‘EndInvoke'” when I call job.Delegate.EndInvoke()? How do I fix it? Note that it likes BeginInvoke() just fine, and doesn’t complain if I add EndInvoke() immediately after BeginInvoke() (thought hat doesn’t accomplish what I want).
I have a little JobTracker class for tracking backup jobs:
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);
}
}
These backup jobs will happen asynchronously via BeginInvoke()/EndInvoke(). The calling code (simplified) looks something like this:
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 – I know this code can be greatly simplified. It’s a first, get-it-working iteration — I just can’t figure out why VS doesn’t like it.
When you call
BeginInvoke, you’re calling it on a specific subclass ofDelegate. When you callEndInvoke, you’re trying to call it onSystem.Delegateitself, which won’t work. Each subclass declares its ownInvoke/BeginInvoke/EndInvokeset of methods – which it has to, given that the signatures of the methods varies according to the signature of the exact delegate type you’re talking about. If you look at the documentation forSystem.Delegateyou won’t find any of those methods there.It’s not really clear what your code is trying to achieve, but if you want to call
EndInvoke, you’ll need to makeJob.Delegatea specific delegate type.