如何在不同线程之间共享数据在C#中不使用静态变量? 我们可以使用属性创建这样的机制吗?
在这种情况下,面向方面的编程会有帮助吗?
为了实现这一点,所有不同的线程都应该在单个对象上工作?
答案 0 :(得分:20)
您无法击败锁定消息队列的简单性。我说不要把时间浪费在任何更复杂的事情上。
阅读锁定声明。
修改强>
以下是Microsoft Queue对象的一个示例,它包含所有针对它的操作都是线程安全的。
public class Queue<T>
{
/// <summary>Used as a lock target to ensure thread safety.</summary>
private readonly Locker _Locker = new Locker();
private readonly System.Collections.Generic.Queue<T> _Queue = new System.Collections.Generic.Queue<T>();
/// <summary></summary>
public void Enqueue(T item)
{
lock (_Locker)
{
_Queue.Enqueue(item);
}
}
/// <summary>Enqueues a collection of items into this queue.</summary>
public virtual void EnqueueRange(IEnumerable<T> items)
{
lock (_Locker)
{
if (items == null)
{
return;
}
foreach (T item in items)
{
_Queue.Enqueue(item);
}
}
}
/// <summary></summary>
public T Dequeue()
{
lock (_Locker)
{
return _Queue.Dequeue();
}
}
/// <summary></summary>
public void Clear()
{
lock (_Locker)
{
_Queue.Clear();
}
}
/// <summary></summary>
public Int32 Count
{
get
{
lock (_Locker)
{
return _Queue.Count;
}
}
}
/// <summary></summary>
public Boolean TryDequeue(out T item)
{
lock (_Locker)
{
if (_Queue.Count > 0)
{
item = _Queue.Dequeue();
return true;
}
else
{
item = default(T);
return false;
}
}
}
}
编辑2
我希望这个例子有所帮助。 记住这是骨头。 使用这些基本思想,您可以安全地利用线程的力量。
public class WorkState
{
private readonly Object _Lock = new Object();
private Int32 _State;
public Int32 GetState()
{
lock (_Lock)
{
return _State;
}
}
public void UpdateState()
{
lock (_Lock)
{
_State++;
}
}
}
public class Worker
{
private readonly WorkState _State;
private readonly Thread _Thread;
private volatile Boolean _KeepWorking;
public Worker(WorkState state)
{
_State = state;
_Thread = new Thread(DoWork);
_KeepWorking = true;
}
public void DoWork()
{
while (_KeepWorking)
{
_State.UpdateState();
}
}
public void StartWorking()
{
_Thread.Start();
}
public void StopWorking()
{
_KeepWorking = false;
}
}
private void Execute()
{
WorkState state = new WorkState();
Worker worker = new Worker(state);
worker.StartWorking();
while (true)
{
if (state.GetState() > 100)
{
worker.StopWorking();
break;
}
}
}
答案 1 :(得分:8)
请查看以下示例代码:
public class MyWorker
{
public SharedData state;
public void DoWork(SharedData someData)
{
this.state = someData;
while (true) ;
}
}
public class SharedData {
X myX;
public getX() { etc
public setX(anX) { etc
}
public class Program
{
public static void Main()
{
SharedData data = new SharedDate()
MyWorker work1 = new MyWorker(data);
MyWorker work2 = new MyWorker(data);
Thread thread = new Thread(new ThreadStart(work1.DoWork));
thread.Start();
Thread thread2 = new Thread(new ThreadStart(work2.DoWork));
thread2.Start();
}
}
在这种情况下,线程类MyWorker
具有变量state
。我们使用相同的对象初始化它。现在您可以看到两个工作人员访问相同 SharedData对象。一个工人所做的更改对另一个人可见。
你还有很多问题。工人2如何知道何时更改了工人1,反之亦然?你如何防止相互冲突的变化?也许阅读:this tutorial。
答案 2 :(得分:6)
您可以将对象作为参数传递给Thread.Start
,并将其用作当前线程和启动线程之间的共享数据存储。
如果您使用ThreadStart
委托的实例表单启动了线程,您也可以直接访问(当然使用适当的锁定)您的数据成员。
您不能使用属性在线程之间创建共享数据。您可以将附加到类的属性实例用作数据存储,但我没有看到它比使用静态或实例数据成员更好。
答案 3 :(得分:3)
当你启动一个线程时,你正在执行某个选定类的方法。该类的所有属性都是可见的。
Worker myWorker = new Worker( /* arguments */ );
Thread myThread = new Thread(new ThreadStart(myWorker.doWork));
myThread.Start();
您的线程现在位于doWork()方法中,可以看到myWorker的任何属性,它本身可能是其他对象。现在你只需要小心处理几个线程同时击中这些属性的情况。