Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.56/48: Рейтинг темы: голосов - 48, средняя оценка - 4.56
0 / 0 / 0
Регистрация: 10.05.2014
Сообщений: 27
1

Как заставить один поток ждать, пока работает другой

15.05.2014, 00:40. Показов 8998. Ответов 11
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте,
стоит такая задача:
есть
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static bool[] forks = new bool[5];// false - свободна
 
public void takeFirstSpoon(int i)
        {
            lock (locker)
            {
               if (!forks[i]){ //если свободна
                    forks[i] = true; //то занять
                }
                else
                {
                    takeFirstSpoon(i); //вот тут, по сути, поток должен сбросить эту блокировку
//и начать заново пытаться занять forks[i]. Но получается, что лок-в-локе-в-локе и т.д.
//Не могу понять, как заставить поток ждать, пока другой освободит forks[i].
//(i -меняется, так что в плане, реально ли другой поток освобождает ячейку, то да.)
                };
            }
 
            takeSecondSpoon(i);
        }
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
15.05.2014, 00:40
Ответы с готовыми решениями:

Как правильно блокировать кнопку пока работает другой поток?
button1.Enabled = false; new Thread(()=> { //работы где-то на 2 минуты ...

Как сделать, чтобы один поток не закончил работу, пока второй работает?
Подскажите, есть например 2 потока, которые ну например отсчитывают в цикле до 100. Как сделать...

Если запустить 2 потока, будет ли один ждать, пока завершится другой
Здравствуйте! Возможно вопрос глупый, но вот никак не пойму Есть цыкл каторый выполняеться n-е...

Как заставить поток ждать, пока не будет выполнено определенное действие?
Добрый день. Решил написать небольшую игру в VB .NET Первая версия оказалась рабочей, однако я ее...

11
158 / 187 / 48
Регистрация: 25.11.2013
Сообщений: 978
15.05.2014, 01:00 2
Опять? Что ты мучаешься, потоки не такая уж и сложная тема, давно бы все выучил.
Кстати, использовать lock в сложных сценариях - дурной тон.
0
0 / 0 / 0
Регистрация: 10.05.2014
Сообщений: 27
15.05.2014, 01:06  [ТС] 3
DataPlanner, в той теме я так и не допоняла, к чему привязывать BeginInvoke.
Спасибо, конечно, за ответ в той теме, но вместо упрёков "как не надо", очень хотела бы увидеть прояснения в ситуации.
0
158 / 187 / 48
Регистрация: 25.11.2013
Сообщений: 978
15.05.2014, 01:59 4
Дорогая девушка, вы постарайтесь понятней изложить суть задачи, очень сложно понять, что вы хотите сделать. Ваш код ни о чем не говорит, изложите словами вашу задачу, думаю, мужская половина форума вам обязательно чиркнет пару строк.
0
insite2012
15.05.2014, 02:01
  #5

Не по теме:

Цитата Сообщение от DataPlanner Посмотреть сообщение
мужская половина форума вам обязательно чиркнет пару строк.
DataPlanner, 100500 :)

0
0 / 0 / 0
Регистрация: 10.05.2014
Сообщений: 27
15.05.2014, 02:11  [ТС] 6
DataPlanner, я уж и не знаю, как объяснить-то.
1) Если использовать BeginInvoke, то к чему его привязывать. Гуглила, все примеры с контролами. Но у меня метод должен вызываться после выполнения определённого условия.
2) Как добиться того, чтобы потоки при каком-то условии (в моём случае forks[i] == true) переходили в режим ожидания. До тех пор, пока другие потоки не поменяют forks[i] на false. И чтоб это всё было потокобезопасно.

Не по теме:

%-)криво всё объясняю, чёрт возьми.

0
158 / 187 / 48
Регистрация: 25.11.2013
Сообщений: 978
15.05.2014, 02:18 7
forks[i] массив, как-то под флаг он мало подходит. Или вы хотите сказать, когда все элементы массива forks[i] будут true или false, должно что-то происходить?
0
0 / 0 / 0
Регистрация: 10.05.2014
Сообщений: 27
15.05.2014, 02:20  [ТС] 8
DataPlanner, когда определённый элемент массива (i, который передаётся в метод), будет true или false, должно что-то происходить.
0
158 / 187 / 48
Регистрация: 25.11.2013
Сообщений: 978
15.05.2014, 02:28 9
Лучший ответ Сообщение было отмечено alexenl как решение

Решение

Попробуйте этот код. Оно?
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class BasicWaitHandle
{
static EventWaitHandle _waitHandle = new AutoResetEvent (false);
static void Main()
{
new Thread (Waiter).Start();
Thread.Sleep (1000); // Pause for a second...
_waitHandle.Set(); // Wake up the Waiter.
}
static void Waiter()
{
Console.WriteLine ("Waiting...");
_waitHandle.WaitOne(); // Wait for notification
Console.WriteLine ("Notified");
}
}
1
0 / 0 / 0
Регистрация: 10.05.2014
Сообщений: 27
15.05.2014, 02:51  [ТС] 10
DataPlanner, дададаадд, кажется, оно! Сейчас пытаюсь присобачить эту штуку, думаю, утром смогу сказать точнее о результате) Спасибо!
0
158 / 187 / 48
Регистрация: 25.11.2013
Сообщений: 978
15.05.2014, 09:30 11
Так я и не понял, что ты там делаешь, но вот тебе еще вариант:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
internal class Program
    {
        private static readonly EventWaitHandle _waitHandle = new AutoResetEvent(false);
        private static bool[] forks;
        private static bool start = true;
 
        private static void TakeFirstSpoon(object input)
        {
            int i = (int)input;
            if (start)
            {
                start = false;
            }
            else
            {
                _waitHandle.WaitOne();
            }
            
            TakeSecondSpoon(i);
        }
 
        private static void TakeSecondSpoon(int i)
        {
            Thread.Sleep(1000);
            forks[i] = true;
            Console.WriteLine("Thread: {0} Index: {1} ", Thread.CurrentThread.GetHashCode(), i);
            _waitHandle.Set();
        }
 
        private static void Main(string[] args)
        {
            forks = new bool[5]; // false - свободна
            forks.Initialize();
            for (int i = 0; i < forks.Length; i++)
            {
                if (!forks[i])
                {
                    var newThread = new Thread(TakeFirstSpoon);
                    newThread.Start(i);
                    Console.WriteLine("Thread: {0} started", newThread.GetHashCode());
                }
            }
            Console.WriteLine();
            Console.ReadLine();
        }
    }
Добавлено через 22 минуты
Вот тебе еще BeginInvoke с музыкой:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
internal class Program
    {
        private static bool[] forks;
 
        private delegate int MethodDelegate(int i);
 
        private static readonly Random r = new Random();
 
        [System.Runtime.InteropServices.DllImport("winmm.DLL", EntryPoint = "PlaySound", SetLastError = true)]
        private static extern bool PlaySound(string szSound, IntPtr hMod, PlaySoundFlags flags);
 
        [System.Flags]
        public enum PlaySoundFlags{SND_ASYNC = 0x0001}
 
        private static void Main()
        {
            MethodDelegate methodDelegate = LongRunMethod;
            forks = new bool[5]; // false - свободна
            forks.Initialize();
            for (int i = 0; i < forks.Length; i++)
            {
                IAsyncResult iAsyncResult = methodDelegate.BeginInvoke(i,new AsyncCallback(AsyncCallbackMethod),methodDelegate);
                // Progress
                int count = 0;
                while (iAsyncResult.IsCompleted == false)
                {
                    if (count > 0)
                    {
                        Console.WriteLine("Main thread {0} seconds waiting for callback...", count);
                    }
                    Thread.Sleep(1000);
                    count++;
                }
            }
 
            Console.WriteLine(":)");
            Console.ReadLine();
        }
 
        private static void AsyncCallbackMethod(IAsyncResult ar)
        {
            MethodDelegate methodDelegate = (MethodDelegate)ar.AsyncState;
            int i = methodDelegate.EndInvoke(ar);
            Console.WriteLine("IAsyncResult for {0} completed. Thread: {1} ", i, Thread.CurrentThread.GetHashCode());
        }
 
        private static int LongRunMethod(int i)
        {
            Thread.Sleep(r.Next(i * 3000));
            forks[i] = true;
            Console.WriteLine("LongRunMethod finished. Index: {0}.", i);
            PlaySound(@"C:\Windows\Media\tada.wav", new IntPtr(), PlaySoundFlags.SND_ASYNC);
            return i;
        }
    }
0
0 / 0 / 0
Регистрация: 10.05.2014
Сообщений: 27
15.05.2014, 15:02  [ТС] 12
DataPlanner, спасибо большое за еще два варианта, но они не пригодились. Я разобралась с тем (AutoResetEvent), и теперь я скорее всего успею доделать курсач Ура-ура-ура
0
15.05.2014, 15:02
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
15.05.2014, 15:02
Помогаю со студенческими работами здесь

Как заставить поток ждать
Есть программа, в которую пользователь может залогиниться, за залогинивание отвечает отдельный...

Как заставить поток ждать в некоторых ситуациях
Есть такой сценарий приложения: Приложение до запуска TCP кеширует данные из MySQL в...

QtConcurrent - заставить главный поток ждать своих детей
Вобщем не успел я разобраться QtConcurrent::run, и тут новая беда :) допустим у меня выполняется...

Ждать, пока работает другая программа
Мне нужно открыть exe-шинк, ждать пока он выполняется, продолжить работу 1-ой программы после...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru