跨线程调用事件?
Calling events cross-threads?
我正在开发一个 class,看起来像这样:
public class MatchmakingService {
private bool working;
private List<MatchmakingUser> matchmakingUsers;
// ...
public MatchmakingService()
{
matchmakingUsers = new List<MatchmakingUser>();
}
public void StartService () {
var thread = new Thread(this.MatchmakingWork);
working = true;
thread.Start();
}
void MatchmakingWork () {
while (working)
{
// some work, match found!
{
if(onMatchFound != null)
onMatchFound(this, new NewMatchEventArgs(matchmakingUsers[i], matchmakingUsers[j]);
}
Thread.Sleep(1000);
}
}
}
通常,当找到匹配项时,我会在 MatchFound 上启动一个事件并结束它,但由于服务的线程不同,并且此事件的订阅者将在不同的线程上 --如何处理?我读过这样做不安全,如果这是真的,那么我有什么选择?
注意:我没有使用 WinForms,所以没有控件的调用恶作剧。
最简单的方法是创建队列。有多种方法可以实现队列。我会在 MatchmakingService
中创建一个队列
使用队列存储匹配项,其他线程必须调用RaiseEvents()
方法来处理队列。这意味着,另一个线程应该有一个 Timer/DispatcherTimer/While 和睡眠等等...
示例:
public class MatchmakingService
{
private bool working;
private List<MatchmakingUser> matchmakingUsers;
// ...
// the queue
private List<NewMatchEventArgs> _queue = new List<NewMatchEventArgs>();
public MatchmakingService()
{
matchmakingUsers = new List<MatchmakingUser>();
}
public void StartService()
{
var thread = new Thread(this.MatchmakingWork);
working = true;
thread.Start();
}
void MatchmakingWork()
{
while (working)
{
// some work, match found!
{
lock (_queue)
_queue.Add(new NewMatchEventArgs(matchmakingUsers[1], matchmakingUsers[2]));
}
Thread.Sleep(1000);
}
}
public void RaiseEvents()
{
NewMatchEventArgs[] copyOfQueue;
// create a copy (bulk action)
lock (_queue)
{
copyOfQueue = _queue.ToArray();
_queue.Clear();
}
// handle the items
if (onMatchFound != null)
foreach (var item in copyOfQueue)
onMatchFound(this, item); // indices are examples
}
public event EventHandler<NewMatchEventArgs> onMatchFound;
}
我正在开发一个 class,看起来像这样:
public class MatchmakingService {
private bool working;
private List<MatchmakingUser> matchmakingUsers;
// ...
public MatchmakingService()
{
matchmakingUsers = new List<MatchmakingUser>();
}
public void StartService () {
var thread = new Thread(this.MatchmakingWork);
working = true;
thread.Start();
}
void MatchmakingWork () {
while (working)
{
// some work, match found!
{
if(onMatchFound != null)
onMatchFound(this, new NewMatchEventArgs(matchmakingUsers[i], matchmakingUsers[j]);
}
Thread.Sleep(1000);
}
}
}
通常,当找到匹配项时,我会在 MatchFound 上启动一个事件并结束它,但由于服务的线程不同,并且此事件的订阅者将在不同的线程上 --如何处理?我读过这样做不安全,如果这是真的,那么我有什么选择?
注意:我没有使用 WinForms,所以没有控件的调用恶作剧。
最简单的方法是创建队列。有多种方法可以实现队列。我会在 MatchmakingService
使用队列存储匹配项,其他线程必须调用RaiseEvents()
方法来处理队列。这意味着,另一个线程应该有一个 Timer/DispatcherTimer/While 和睡眠等等...
示例:
public class MatchmakingService
{
private bool working;
private List<MatchmakingUser> matchmakingUsers;
// ...
// the queue
private List<NewMatchEventArgs> _queue = new List<NewMatchEventArgs>();
public MatchmakingService()
{
matchmakingUsers = new List<MatchmakingUser>();
}
public void StartService()
{
var thread = new Thread(this.MatchmakingWork);
working = true;
thread.Start();
}
void MatchmakingWork()
{
while (working)
{
// some work, match found!
{
lock (_queue)
_queue.Add(new NewMatchEventArgs(matchmakingUsers[1], matchmakingUsers[2]));
}
Thread.Sleep(1000);
}
}
public void RaiseEvents()
{
NewMatchEventArgs[] copyOfQueue;
// create a copy (bulk action)
lock (_queue)
{
copyOfQueue = _queue.ToArray();
_queue.Clear();
}
// handle the items
if (onMatchFound != null)
foreach (var item in copyOfQueue)
onMatchFound(this, item); // indices are examples
}
public event EventHandler<NewMatchEventArgs> onMatchFound;
}