我有一个Azure应用程序需要3个独特的任务才能作为长时间运行的进程运行。我可以很容易地调整3个工作者角色,但考虑到任务的简单性,这将比我需要花费多3倍。我想在自己的线程中运行每个任务,因为每个任务的完成时间和运行需要的频率都非常不同。
鉴于这种情况,甚至是一般的多线程Azure场景,您知道让每项任务独立运行的最佳方式是什么?
我想提出的一些考虑因素是:
感谢您提供建议,链接或代码示例。
修改
以下是我已经解决的问题 - 鉴于代码绑定到Azure云,自我修复选项似乎是最合适的。这种方法旨在采用一系列线程并将其工作委托给各种“工作单元”。
这是如何粘在一起的。首先,一个简单的课程,包括多种工人。
public class ThreadWorker
{
internal void RunInternal()
{
try
{
Run();
}
catch (SystemException)
{
throw;
}
catch (Exception)
{
}
}
public virtual void Run()
{
}
public virtual void OnStop()
{
}
}
接下来,使一系列线程无限期保持活动的代码。这涉及一个线程列表,一个“worker”列表(每个线程一个),以及一个无限循环,用于检查给定时间间隔内每个线程的状态。
请注意,终止线程的异常不会拆除其他线程。如果遇到未处理的异常,则下次事件等待句柄响应时将重新启动该线程。
private readonly List<Thread> _threads = new List<Thread>();
private readonly List<ThreadWorker> _workers = new List<ThreadWorker>();
private EventWaitHandle EventWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
public override void Run()
{
foreach (var worker in _workers)
{
_threads.Add(new Thread(worker.RunInternal));
}
foreach (var thread in _threads)
{
thread.Start();
}
while (!EventWaitHandle.WaitOne(500))
{
// Restart any threads that have stopped running
for (var i = 0; i < _threads.Count; i++)
{
if (_threads[i].IsAlive)
{
continue;
}
_threads[i] = new Thread(_workers[i].RunInternal);
_threads[i].Start();
}
EventWaitHandle.WaitOne(2000);
}
}
足够简单 - 主线程(在本例中为Azure工作者角色的Run方法)在检查到活动的线程列表之间阻塞半秒。重新启动终止的线程,然后主机线程阻塞2秒,然后再次检查工作线程的运行状况。
添加worker就像添加从ThreadWorker基类继承的类列表一样简单
_workers.Add(new SomeWorker());
_workers.Add(new AnotherWorker());
最后,具体工人:
public class SomeWorker: ThreadWorker
{
public override void Run()
{
while (true)
{
// Do your long running work here.
Thread.Sleep(2000); // Take a breather - not necessary.
}
}
}
public class AnotherWorker: ThreadWorker
{
public override void Run()
{
while (true)
{
// Do your long running work here.
}
}
}
答案 0 :(得分:3)
我认为这是一个非常常见的情况 - 在一个理想的世界中,每个角色只有一份工作,但出于现金原因(以及环境原因!),最好将它们合并为一个角色。
我个人认为没有正确的方法 - 有多种选择,您需要选择最适合您应用当前要求的选项:
答案 1 :(得分:1)
你的问题不是一个独特的天蓝色问题,它只是单个CPU上的经典线程。 (如果您在单个实例中运行多个CPU,那么您也可以运行单独的实例,这是相同的成本。)
我是TPL的忠实粉丝,它已经为你解决了许多常见问题,所以我认为应该这样做。
答案 2 :(得分:0)
使每个任务成为一个单独的.exe并从您的WorkerRole类中启动它们。从那里监视意外终止的进程(Process.WaitForExit()),并再次启动它们。 (但考虑如果一个进程不断崩溃会发生什么 - 它将使用100%CPU启动,崩溃并再次启动。也许使用指数退避来管理它。)
我假设您只有一个角色实例用于这三个任务,在这种情况下,您还必须考虑系统如何处理由于硬件故障或其他原因而偶尔由Azure关闭和重启。 (对于多个实例,它们不太可能一起失败。)
答案 3 :(得分:0)
我将为这些长寿任务中的每一个开始一个线程。
实际上,这就是我在其中一个角色中所做的:Run multiple WorkerRoles per instance
我加载类型并在单独的线程中调用Run方法。