I've found few questions concerning my problem but still, I couldn't hande with this on my own so I'll try to ask in here. I'll paste the code so I think it will be easier to explain.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Thread thread = new Thread(new ThreadStart(StartCalculation));
thread.Start();
}
private void Form1_Load(object sender, EventArgs e)
{
}
public void StartCalculation()
{
List<int> numbers = new List<int>();
for (int i = 0; i <= 100; i++)
{
numbers.Add(i);
string textForLabel = i.ToString();
label.SafeInvoke(d => d.Text = textForLabel);
}
}
}
Edited for Groo- / -
public partial class Form1 : Form
{
List<int> list = new List<int>(); // list of int values from game's memory
public Form1()
{
InitializeComponent();
Thread thread = new Thread(new ThreadStart(refreshMemory));
thread.Start();
Thread thread2 = new Thread(new ThreadStart(checkMemory));
thread2.Start();
}
private void Form1_Load(object sender, EventArgs e)
{
}
public void refreshMemory()
{
while (true)
{
// ... refresh game's memory and then, refresh list //
Thread.Sleep(100);
}
}
public void checkMemory()
{
while (true)
{
// eg. if (list[0] == 5) {game:: move_right()}//
Thread.Sleep(100);
}
}
}
I'm making game bot. I want it to read game's memory in a different thread (changing memory list) and then, with few other methods (in different threads) I'd like to read from that list and do game actions depending on the memory values. It works (or just seem to be) but if You say it might be unsafe, I'd like to make it safe.
Hope I haven't made fool out of myself by pasting it here.
If you want synchronous communication between a main thread and a processing thread, you can use a SynchronousQueue. The idea is that the main thread passes data to the processing thread by calling put() , and the processing thread calls take() . Both are blocking operations.
Every thread shares common addressing space, so a local variable inside a thread can be seen by another thread using pointers.
Can we write multithreading programs in C? Unlike Java, multithreading is not supported by the language standard. POSIX Threads (or Pthreads) is a POSIX standard for threads.
A data race is a state, in which at least two threads access shared data at the same time, and at least one of the threads is a writer. A critical section is a section of the code, which not more than one thread should access at any point in time.
You need some form of a synchronization mechanism to modify objects between multiple threads. If you don't use a specialized thread safe collection (these are available in .NET 4), you need to lock using a monitor.
Usually, a more appropriate collection type for the producer/consumer pattern is a Queue
(a FIFO collection), instead of a List
:
Plain Queue with explicit locking
private readonly object _lock = new object();
private readonly Queue<Item> _queue = new Queue<Item>();
private readonly AutoResetEvent _signal = new AutoResetEvent();
void ProducerThread()
{
while (ShouldRun)
{
Item item = GetNextItem();
// you need to make sure only
// one thread can access the list
// at a time
lock (_lock)
{
_queue.Enqueue(item);
}
// notify the waiting thread
_signal.Set();
}
}
And in the consumer thread, you need to fetch the item and process it:
void ConsumerThread()
{
while (ShouldRun)
{
// wait to be notified
_signal.Wait();
Item item = null;
do
{
item = null;
// fetch the item,
// but only lock shortly
lock (_lock)
{
if (_queue.Count > 0)
item = _queue.Dequeue(item);
}
if (item != null)
{
// do stuff
}
}
while (item != null); // loop until there are items to collect
}
}
Starting with .NET 4, there is a ConcurrentQueue<T>
collection, a thread-safe FIFO, which removes the need to lock while accessing it and simplifies the code:
ConcurrentQueue
private readonly ConcurrentQueue<Item> _queue = new ConcurrentQueue<Item>();
void ProducerThread()
{
while (ShouldRun)
{
Item item = GetNextItem();
_queue.Enqueue(item);
_signal.Set();
}
}
void ConsumerThread()
{
while (ShouldRun)
{
_signal.Wait();
Item item = null;
while (_queue.TryDequeue(out item))
{
// do stuff
}
}
}
Finally, if you only wish that your consumer thread gets items in chunks periodically, you would change this to:
ConcurrentQueue with threshold (10 sec. or 10 items)
private readonly ConcurrentQueue<Item> _queue = new ConcurrentQueue<Item>();
void ProducerThread()
{
while (ShouldRun)
{
Item item = GetNextItem();
_queue.Enqueue(item);
// more than 10 items? panic!
// notify consumer immediately
if (_queue.Count >= 10)
_signal.Set();
}
}
void ConsumerThread()
{
while (ShouldRun)
{
// wait for a signal, OR until
// 10 seconds elapses
_signal.Wait(TimeSpan.FromSeconds(10));
Item item = null;
while (_queue.TryDequeue(out item))
{
// do stuff
}
}
}
This pattern is so useful that it's nice to abstract it into a generic class which delegates producing and consuming to external code. It would be a good exercise to to make it generic.
You will also need a Stop
method which will probably set a volatile bool
flag indicating that it's time to stop, and then set the signal to unpause the consumer and allow it to end. I will leave this to you as an exercise.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With