我感觉自己就像一个总的菜鸟问这个,但无论如何,这里就是:
我想知道从不同线程同步事件的最简单方法是什么。
一些示例代码:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("# started on:" + Thread.CurrentThread.ManagedThreadId);
tt t = new tt();
t.First += new EventHandler(t_First);
t.Second += new EventHandler(t_Second);
Task task = new Task(new Action(t.Test));
task.Start();
while (true)
{
Console.ReadKey();
Console.WriteLine("# waiting on:" + Thread.CurrentThread.ManagedThreadId);
}
}
static void t_Second(object sender, EventArgs e)
{
Console.WriteLine("- second callback on:" + Thread.CurrentThread.ManagedThreadId);
}
static void t_First(object sender, EventArgs e)
{
Console.WriteLine("- first callback on:" + Thread.CurrentThread.ManagedThreadId);
}
class tt
{
public tt()
{
}
public event EventHandler First;
public event EventHandler Second;
public void Test()
{
Thread.Sleep(1000);
Console.WriteLine("invoked on:" + Thread.CurrentThread.ManagedThreadId);
First(this, null);
Thread.Sleep(1000);
Second(this, null);
}
}
}
正如你可能猜到的那样,只有第一个写字线在主线程上执行,其他调用都在任务创建的新线程上执行。
我想在主线程上同步对“Second”的调用(它应该永远不会被调用,因为我在while循环中阻塞)。但是,我想知道这样做的方式,或者它是否可能?
答案 0 :(得分:6)
您可以尝试BlockingCollection
BlockingCollection<Action> actions = new BlockingCollection<Action>();
void main() {
// start your tasks
while (true) {
var action = actions.Take();
action();
}
}
static void t_First(object sender, EventArgs e) {
string message = "- first callback on:" + Thread.CurrentThread.ManagedThreadId;
actions.Add(_ => Console.WriteLine(message));
}
答案 1 :(得分:-1)
如果我理解你的话,你就会问如何将在线程上运行的代码执行到不同的线程中。即:你有两个线程,而你正在执行第二个线程代码,你想在第一个线程中执行它。
您可以使用SynchronizationContext
来实现此目的,例如,如果您想从另一个线程执行代码到主线程,您应该使用当前的同步上下文:
private readonly System.Threading.SynchronizationContext _currentContext = System.Threading.SynchronizationContext.Current;
private readonly object _invokeLocker = new object();
public object Invoke(Delegate method, object[] args)
{
if (method == null)
{
throw new ArgumentNullException("method");
}
lock (_invokeLocker)
{
object objectToGet = null;
SendOrPostCallback invoker = new SendOrPostCallback(
delegate(object data)
{
objectToGet = method.DynamicInvoke(args);
});
_currentContext.Send(new SendOrPostCallback(invoker), method.Target);
return objectToGet;
}
}
当你在第二个线程中时,使用此方法将在主线程上执行代码。
您可以实现ISynchronizeInvoke“System.ComponentModel.ISynchronizeInvoke”。检查this示例。
修改:由于您正在运行控制台应用程序,因此无法使用SynchronizationContext.Current
。那么您可能需要设计自己的SynchronizationContext
,this示例可能有帮助。