PDA

View Full Version : حرفه ای: ایجاد ناحیه بحرانی بین یک تایمر و یک ترد



alimooghashang
پنج شنبه 09 شهریور 1391, 11:07 صبح
سلام
من یه تایمر دارم با اینتروال 2 ثانیه و یک ترد که باید یک سری کار انجام بده
تایمر یک آرایه رو پر میکنه و ترد اون آرایه رو خالی
و باید جوری باشه که ترد وقتی آرایه خالیه کاری نکنه
چطوری باید یک ناحیه بحرانی این وسط تعریف کنم ؟
ممنون

alitavakoli
پنج شنبه 09 شهریور 1391, 11:39 صبح
اگه ممکنه قسمتی از کد رو قرار بدین تا بهتر متوجه شم که دقیقا چه کاری میخواین انجام بدین.
اگه از background worker برای این کار استفاه کردید کافیه چک کنید که ارایه خالی هست یا نه اگه آرایه خالی بود ترد رو کنسل کنید

the king
پنج شنبه 09 شهریور 1391, 20:14 عصر
سلام
من یه تایمر دارم با اینتروال 2 ثانیه و یک ترد که باید یک سری کار انجام بده
تایمر یک آرایه رو پر میکنه و ترد اون آرایه رو خالی
و باید جوری باشه که ترد وقتی آرایه خالیه کاری نکنه
چطوری باید یک ناحیه بحرانی این وسط تعریف کنم ؟
ممنون

ابتدای کلاس یک شیء بسازید :

object obj = new object();


و هر جا که قراره ناحیه بحرانی باشه روی اون شیء lock کنید (داخل بلوک lock ناحیه بحرانی یه)

lock (obj)
{


}

tooraj_azizi_1035
پنج شنبه 09 شهریور 1391, 20:22 عصر
به این کار شما سناریوی Producer/Consumer گفته می شه. یک ترد داده ها رو تولید و دیگری مصرف می کنه.

سعی کنید از ConcurrentCollections استفاده کنید : http://msdn.microsoft.com/en-us/vstudio/gg274329.aspx

استفاده از تایمر رو اگر حتماً می خواهید در بازه زمانی خاص داده ها رو مصرف کنید مانعی نداره اما اگه نه استفاده از اون اشتباهه و باید یه ترد داده ها رو تولید و دیگری مصرف کنه با ساختمان داده جدید در دات نت 4 که خط بالا گفتم نیازی به هماهنگی برای ThreadSafety نیست چون خودش این کار رو می کنه در ضمن اگه داده ای در آرایه نباشه چیزی مصرف نمی کنه.

class Program
{
static void Main(string[] args)
{
Object lockObj = new object();
Queue<string> queue = new Queue<string>();
Producer p = new Producer(queue, lockObj);
Consumer c1 = new Consumer(queue, lockObj, "c1");
Consumer c2 = new Consumer(queue, lockObj, "c2");

Thread t1 = new Thread(c1.consume);
Thread t2 = new Thread(c2.consume);
t1.Start();
t2.Start();

Thread t = new Thread(p.produce);
t.Start();

Console.ReadLine();
}
}
public class Producer
{
Queue<string> queue;
Object lockObject;
static int seq = 0;
public Producer(Queue<string> queue, Object lockObject)
{
this.queue = queue;
this.lockObject = lockObject;
}

public void produce()
{
while( seq++ <15) //just testinng 15 items
{
lock (lockObject)
{
string item = "item" + seq;
queue.Enqueue(item);
Console.WriteLine("Producing {0}", item);
if (queue.Count == 1)
{ // first
Monitor.PulseAll(lockObject);
}
}
}
}

}

public class Consumer
{
Queue<string> queue;
Object lockObject;
string name;
public Consumer(Queue<string> queue, Object lockObject, string name)
{
this.queue = queue;
this.lockObject = lockObject;
this.name = name;
}

public void consume()
{
string item;
while (true)
{
lock (lockObject)
{
if (queue.Count == 0)
{
Monitor.Wait(lockObject);
continue;
}
item = queue.Dequeue();
Console.WriteLine(" {0} Consuming {1}", name, item);
}
}
}
}