Подтвердить что ты не робот

Как обмениваться данными между различными потоками В С# с использованием AOP?

Как обмениваться данными между разными потоками В С# без использования статических переменных? Можем ли мы создать такой маханизм с использованием атрибута?

Будет ли поддержка ориентированного программирования Aspect в таких случаях?

Чтобы добиться этого, все разные потоки должны работать на одном объекте?

4b9b3361

Ответ 1

Вы можете передать объект в качестве аргумента Thread.Start и использовать его в качестве общего хранилища данных между текущим потоком и инициирующим потоком.

Вы также можете напрямую получить доступ (с соответствующей блокировкой) ваших членов данных, если вы начали поток, используя форму экземпляра ThreadStart.

Вы не можете использовать атрибуты для создания общих данных между потоками. Вы можете использовать экземпляры атрибутов, прикрепленные к вашему классу, как хранилище данных, но я не вижу, как это лучше, чем использование статических или экземпляров данных.

Ответ 2

Вы не можете победить простоту заблокированной очереди сообщений. Я говорю, не тратьте время на что-то более сложное.

Прочитайте инструкцию lock.

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;
        }
    }                   
}

Ответ 3

Посмотрите на следующий пример кода:

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 и наоборот? Как вы предотвращаете конфликтующие изменения? Возможно, читайте: этот учебник.

Ответ 4

При запуске потока вы выполняете метод некоторого выбранного класса. Все атрибуты этого класса видны.

  Worker myWorker = new Worker( /* arguments */ );

  Thread myThread = new Thread(new ThreadStart(myWorker.doWork));

  myThread.Start();

Ваш поток теперь находится в методе doWork() и может видеть любые атрибуты myWorker, которые сами могут быть другими объектами. Теперь вам просто нужно быть осторожным, чтобы иметь дело с случаями одновременного нажатия нескольких потоков на эти атрибуты.