我有2个线程调用“Task.Factory.StartNew”。我们只说一个线程(ThreadA)比另一个线程(ThreadB)略强。
...在主题A中,稍微调用
Task.Run(() => {
SomeMethodInThreadA();
});
...在主题B中稍后调用
Task.Run(() => {
SomeMethodInThreadB();
});
TaskScheduler 是否保证在 SomeMethodInThreadB 之前先执行 SomeMethodInThreadA ?
如果没有,我该怎么做?使用Task.Factory.StartNew并传入特殊的TaskScheduler?
此外,除了保证首先处理SomeMethodInThreadA之外,我还要确保 SomeMethodInThreadA 在执行 SomeMethodInThreadB 之前先完成。
我已经考虑使用StaTaskScheduler,但我不确定这是否是解决方案。
修改
我没有透露太多关于我继承的程序的细节/戏剧,我想我正在寻找的是一个自定义的TaskScheduler:
代表队列排队时的序列
连续执行
在同一个线程中执行,类似于我上面链接的StaTaskScheduler源代码
答案 0 :(得分:3)
没有给出关于该计划的太多细节/戏剧我 继承,我想我要找的是一个自定义的TaskScheduler 其中:
代表队列排队时的序列
连续执行
- 醇>
在同一个线程中执行,类似于我上面链接的StaTaskScheduler源代码
如果这就是你想要的全部,你需要做一个BlockingCollection<Action>
然后在专用线程上遍历列表。
public class BackgroundJobSchedueller
{
readonly BlockingCollection<Action> _queue;
readonly Thread _thread;
public BackgroundJobSchedueller()
{
_queue = new BlockingCollection<Action>()
_thread = new Thread(WorkThread)
{
IsBackground = true,
Name = "Background Queue Processor"
};
_thread.Start();
}
public void StopSchedueller()
{
//Tell GetConsumingEnumerable() to let the user out of the foreach loop
// once the collection is empty.
_queue.CompleteAdding();
//Wait for the foreach loop to finish processing.
_thread.Join();
}
public void QueueJob(Action job)
{
_queue.Add(job);
}
void WorkThread()
{
foreach(var action in _queue.GetConsumingEnumerable())
{
try
{
action();
}
catch
{
//Do something with the exception here
}
}
}
}
如果没有工作要做,线程会休眠,在foreach上被阻塞,一旦你将一个项目添加到队列中,它就会被处理,然后再回到睡眠状态。
答案 1 :(得分:0)
TaskScheduler是否保证在SomeMethodInThreadB之前首先执行SomeMethodInThreadA?
没有
让第二项任务成为您第一项任务的延续如果没有,我该怎么做?
类似的东西:
var task = Task.Run(() => {
SomeMethodInThreadA();
});
然后:
task.ContinueWith(t => {
SomeOtherMethodInThreadA();
});
答案 2 :(得分:0)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Task.Factory.StartNew(() => MethodA())
.ContinueWith(a =>
{
MethodB();
});
Console.WriteLine("Press a key to exit");
Console.ReadKey(false);
}
public static void MethodA()
{
Thread.Sleep(2000);
Console.WriteLine("Hello From method A {0}", Thread.CurrentThread.ManagedThreadId);
}
public static void MethodB()
{
Thread.Sleep(1000);
Console.WriteLine("Hello From method B {0}", Thread.CurrentThread.ManagedThreadId);
}
}
}
答案 3 :(得分:0)
TaskScheduler是否保证SomeMethodInThreadA得到 先在SomeMethodInThreadB之前执行?
当然不是。
如果没有,我该怎么做?
如果2个线程彼此完全独立,但SomeMethodInThreadB
必须在SomeMethodInThreadA
完成后执行,则可以使用标准线程同步例程:
public static AutoResetEvent Wait = new AutoResetEvent(false);
然后在开始第一个任务时:
var task = Task.Run(() =>
{
// Sets the state of the event to nonsignaled, causing threads to block.
Wait.Reset();
// Execute the first task
SomeMethodInThreadA();
// The first task has finished executing -> signal the second
// thread which is probably waiting that it can start processing
// the second task
Wait.Set();
});
然后在第二个线程中等待发出第一个方法已完成执行的信号:
Task.Run(() =>
{
if (!Wait.WaitOne(TimeSpan.FromMinutes(30)))
{
// We have waited for too long the first task to execute - giving up
}
else
{
// The first task has finished executing - we can now
// proceed with the second task
SomeMethodInThreadB();
}
});
显然,您需要定义第二个线程在放弃之前等待第一个任务完成的时间。