views:

2373

answers:

4

How to share data between different threads In C# without using the static variables? Can we create a such machanism using attribute?

Will Aspect oriented programming help in such cases?

To acheive this all the different threads should work on single object?

+5  A: 

You can't beat the simplicity of a locked message queue. I say don't waste your time with anything more complex.

Read up on the lock statement.

lock

EDIT

Here is an example of the Microsoft Queue object wrapped so all actions against it are thread safe.

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

EDIT 2

I hope this example helps. Remember this is bare bones. Using these basic ideas you can safely harness the power of threads.

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;
     }
    }     
}
ChaosPandion
+1: Yep.
John Gietzen
It's not like a message queue is suitable for any purpose...
Thorarin
Not even passing messages?
ChaosPandion
We are trying to read the available object instance in one thread into another thread, and we have a restriction to maintain global/static variable, is there some good idea to acheive it?
Jaswant Agarwal
+1  A: 

When you start a thread you are executing a method of some chosen class. All attributes of that class are visible.

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

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

  myThread.Start();

Your thread is now in the doWork() method and can see any atrributes of myWorker, which may themselves be other objects. Now you just need to be careful to deal with the cases of having several threads all hitting those attributes at the same time.

djna
yep..Your Idea is very much usefull, let me elaborate my situation here asWe are trying to read the available object instance in one thread into another thread, and we have a restriction to maintain global/static variable, is there some good idea to acheive it?
Jaswant Agarwal
You did not elaborate you simply repeated your original question.
ChaosPandion
Please read my comment on your question. I want to explain further but I need you help.
djna
okk..Suppose one instance of a class in one thread, and another thread want to read the data available in that class instance variable, can it be done by applying some attribute on the varible?
Jaswant Agarwal
Please do this: edit your question, add code snippet to show the relevent classes. You need only a very few lines. We can then show you how to do this. It's **much** easier than you seem to think. So much easier to explain with reference to some cide.
djna
+1  A: 

You can pass an object as argument to the Thread.Start and use it as a shared data storage between the current thread and the initiating thread.

You can also just directly access (with the appropriate locking of course) your data members, if you started the thread using the instance form of the ThreadStart delegate.

You can't use attributes to create shared data between threads. You can use the attribute instances attached to your class as a data storage, but I fail to see how that is better than using static or instance data members.

Franci Penov
To use as a shared data storage again need to go for some Static/Global variable?
Jaswant Agarwal
The code that started the thread obviously has a reference to the object passed as a parameter to the Thread.Start. The thread procedure also has a reference to that object. Thus, but pieces of code can write to it without that object having to be a static variable.
Franci Penov
yes.. i got it..will you please write some code snippet for better understanding
Jaswant Agarwal
+3  A: 

Look at the following example code:

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

In this case, the thread class MyWorker has a variable state. We initialise it with the same object. Now you can see that the two workers access the same SharedData object. Changes made by one worker are visible to the other.

You have quite a few remaining issues. How does worker 2 know when changes have been made by worker 1 and vice-versa? How do you prevent conflicting changes? Maybe read: this tutorial.

Aamir
Yap..its near by but not exact ..here two threads bbut same instance of myworker class,for me two instance of MyWorker class (work1 and work2) in different threads and want to read data from work1 in thread2..how can we do it?
Jaswant Agarwal
In that case, you will need to pass the work1 object to the thread2. You can do this by using ParameterizedThreadStart instead of ThreadStart.
Aamir
@Amir hope you don't mind, I adjusted the example to match Jaswant's description
djna
@djna: No problem. This is exactly the true purpose of a community-based site. I initially gave him a very trivial example to get him started.
Aamir
Thanks aamir..it was wht i want:)
Jaswant Agarwal
Should thank djna. He made it into what you wanted :)
Aamir