WebApi中的后台工作者 [英] Background workers in WebApi

查看:59
本文介绍了WebApi中的后台工作者的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图弄清楚我对API调用的请求是如何等待后台工作完成的.

I'm trying to figure out how it comes that my request to an API call is waiting for my backgroundworkers to be completed.

这是我的jobManager:

This is my 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

this is 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.

So I wanted in my controller to create 10 jobs and return the Id's while the tasks are running in the background.

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 id 上放置断点时,它击中的速度非常快(因此异步正在工作)

This all seem to work great, except that the request is waiting on the sleeptimer in the job. although when I place a breakpoint on return ids in my controller; it hit's it very fast (so the async is working)

推荐答案

通常,您应该收到以下消息:异步模块或处理程序在异步操作仍待处理时完成.">启动背景被认为是危险的任务无需等待

Normally you should have the message: "An asynchronous module or handler completed while an asynchronous operation was still pending." It is considered as dangerous to launch background tasks without awaiting them

您应该使用TaskParallelLibrary-async/await做到这一点,并正确等待所有Tasks返回:

You should use the TaskParallelLibrary - async/await do do that and properly wait for all the Tasks to return:

 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);
        }

如果您正在执行FireAndForget,则可以使用框架4.5中的新 QueueBackgroundWorkItem .2.

If you are doing FireAndForget you can use the new QueueBackgroundWorkItem from framework 4.5.2.

也请查看此帖子.最好使用本机异步方法并将整个链转换为异步,而不是简单地执行"Task.Run".

Also check out this Post. It is better to use the native async methods and to transform the whole chain to async instead of simply doing "Task.Run".

这篇关于WebApi中的后台工作者的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆