2015-07-17 5 views
0

Я пытаюсь выяснить, как получается, что мой запрос на вызов API ждет завершения моих фоновых работников.Фоновые работники в WebApi

Это мой JobManager:

public class JobManager { 
public List<AbstractJob> Jobs; 

public JobManager() { 
    Jobs = new List<AbstractJob>(); 
} 

public int newTestJob() { 
    var job = new TestJob(); 
    job.Name = "TestJob"; 
    Jobs.Add(job); 
    return job.Id; 
} 

public void startJob(int id) { 
    var job = Jobs.Where(j => j.Id == id).FirstOrDefault(); 
    if (job == null) throw new Exception("not found"); 

    job.Execute(); 
} 

public string statusJob(int id) { 
    var job = Jobs.Where(j => j.Id == id).FirstOrDefault(); 
    if (job == null) throw new Exception("not found"); 

    return job.Status; 
} 

public List<AbstractJob> runningJobs() { 
    return Jobs.Where(j => j.Status == "Running").ToList(); 
} 
} 

это является IJob

public interface IJob { 
    void Execute(); 
} 

это AbstractJob

public abstract class AbstractJob : IJob { 
    static int counter = 0; 
    protected BackgroundWorker _bw = new BackgroundWorker(); 
    public int Id; 
    public string Status; 
    public string Name; 

    public AbstractJob() { 
    Interlocked.Increment(ref counter); 
    Id = counter; 
    _bw.WorkerReportsProgress = true; 
    _bw.WorkerSupportsCancellation = true; 
    _bw.DoWork += new DoWorkEventHandler(bw_DoWork); 
    _bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged); 
    _bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); 
    _bw.ReportProgress(0, "Idle"); 
    } 

    public virtual string Describe() { 
    return "Not much is known about this four legged animal!"; 
    } 

    public void Execute() { 
    _bw.RunWorkerAsync(); 
    } 
    private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e) { 
    this.Status = e.UserState.ToString(); 
    } 

    private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { 
    BackgroundWorker worker = sender as BackgroundWorker; 
    if ((e.Cancelled == true)) { 
     this.Status = "Canceled"; 
    } else if (!(e.Error == null)) { 
     this.Status = "Error"; 

    } else { 
     this.Status = "Done"; 
    } 
    } 
    public abstract void bw_DoWork(object sender, DoWorkEventArgs e); 
} 

И сказать, что это моя работа:

public class TestJob : AbstractJob { 
    public override void bw_DoWork(object sender, DoWorkEventArgs e) { 
    System.Threading.Thread.Sleep(50000); // representing some actual code that takes time 
    } 
} 

Таким образом, я хотел, чтобы в моем контроллере было создано 10 заданий и возвращалось Id во время выполнения задач в фоновом режиме.

public IEnumerable<int> Get() { 
    var ids = new List<int>(); 
    for (int i = 0; i < 10; i++) { 
    var id = jobm.newTestJob(); 
    jobm.startJob(id); 
    ids.Add(id); 
    } 

    return ids; 
} 

Все это, кажется, отлично работает, за исключением того, что запрос ожидает от пользователя sleeptimer. хотя когда я устанавливаю точку останова на return ids в моем контроллере; это очень быстро (так работает async)

ответ

2

Обычно вы должны иметь сообщение: «Асинхронный модуль или обработчик завершен, пока асинхронная операция все еще находится в ожидании». It is considered as dangerous to launch background tasks without awaiting them

Вы должны использовать TaskParallelLibrary - асинхронный/Await, делает это и правильно ждать всех задачи, чтобы вернуться:

public async Task Get() 
     { 
      var tasks = new List<Task>(); 
      for (int i = 0; i < 10; i++) 
      { 
       tasks.Add(Task.Run(() => 
       { 
        //your code here 
       })); 
      } 
      await Task.WhenAll(tasks); 
     } 

Если вы делаете головку самонаведения вы можете использовать новый QueueBackgroundWorkItem из рамок 4.5. 2.

Также ознакомьтесь с этим Post. Лучше использовать собственные асинхронные методы и преобразовать целую цепочку в async вместо простого выполнения «Task.Run».

+0

Спасибо, теперь попробуйте другой подход (через службу Windows и таблицу SQL) – Kiwi

Смежные вопросы