如何在C#中使用AOP在不同线程之间共享数据?

时间:2009-09-01 04:33:28

标签: c# multithreading

如何在不同线程之间共享数据在C#中不使用静态变量? 我们可以使用属性创建这样的机制吗?

在这种情况下,面向方面的编程会有帮助吗?

为了实现这一点,所有不同的线程都应该在单个对象上工作?

4 个答案:

答案 0 :(得分:20)

您无法击败锁定消息队列的简单性。我说不要把时间浪费在任何更复杂的事情上。

阅读锁定声明。

lock

修改

以下是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的任何属性,它本身可能是其他对象。现在你只需要小心处理几个线程同时击中这些属性的情况。