Синхронизация двух потоков - PullRequest
2 голосов
/ 12 мая 2009

У меня есть два потока в c #. Теперь мне нужно дождаться выполнения определенного оператора, прежде чем я смогу продолжить выполнение в другом потоке, что, очевидно, является случаем синхронизации. Есть ли код, который может выполнить это, как при использовании встроенного метода?

Это пример кода:

    public void StartAccept()
    {
            try
            {
                newSock.BeginAccept(new AsyncCallback(Accepted), newSock);
            }
            catch (ArgumentException)
            {
                MessageBox.Show("Error in arguments while using begin-accept", "Error", MessageBoxButtons.OK);
            }
            catch (ObjectDisposedException)
            {
                MessageBox.Show("socket closed while using begin-accept", "Error", MessageBoxButtons.OK);
            }
            catch (SocketException)
            {
                MessageBox.Show("Error accessing socket while using begin-accept", "Error", MessageBoxButtons.OK);
            }
            catch (InvalidOperationException)
            {
                MessageBox.Show("Invalid operation while using begin-accept", "Error", MessageBoxButtons.OK);
            }
            catch (Exception)
            {
                MessageBox.Show("Exception occurred while using begin-accept", "Error", MessageBoxButtons.OK);
            }

    }

Получает данные от желаемого хоста, который выбран кодом:

    private void listBox1_Click(object sender, EventArgs e)
    {



        String data = (String)this.listBox1.SelectedItem;

        ip = Dns.GetHostAddresses(data);

        clientIP = new IPEndPoint(ip[0], 5555);

        newSock.Bind(clientIP);
        newSock.Listen(100);

    }

Итак, чтобы начать получать данные, мне нужно инициализировать сокет для конкретного удаленного хоста, что делается, когда я нажимаю на один из хостов, показанных в списке. Для этого мне нужна синхронизация.

Ответы [ 3 ]

11 голосов
/ 12 мая 2009

Взгляните на AutoResetEvent и ManualResetEvent . Это сигналы, которые делают возможной синхронизацию между потоками.

Первый поток, которому нужно дождаться, чтобы что-то было сделано, выполнит myEvent. WaitOne (), который блокирует, пока другой поток не вызовет myEvent. Set ().

Допустим, у нас есть два потока, один из которых должен выполнить некоторую инициализацию, прежде чем другой поток сможет продолжить. Затем вы разделяете AutoResetEvent между двумя, давайте назовем его myEvent.

// Signal example

using System;
using System.Threading;

class MySync
{
    private readonly AutoResetEvent _myEvent;
    public MySync(AutoResetEvent myEvent)
    {
        _myEvent = myEvent;
    }

    public void ThreadMain(object state)
    {
        Console.WriteLine("Starting thread MySync");
        _myEvent.WaitOne();
        Console.WriteLine("Finishing thread MySync");
    }
}

class Program
{
    static void Main(string[] args)
    {
        AutoResetEvent myEvent = new AutoResetEvent(false);
        MySync mySync = new MySync(myEvent);
        ThreadPool.QueueUserWorkItem(mySync.ThreadMain);
        Console.WriteLine("Press enter to continue...");
        Console.ReadLine();
        myEvent.Set();
        Console.WriteLine("Press enter to continue...");
        Console.ReadLine();
        Console.WriteLine("Finishing");
    }
}

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

// Mutex example

object mySync = new object();
Dictionary<int, int> myDict = new Dictionary<int, int>();

void threadMainA()
{
    lock(mySync)
    {
        mySync[foo] = bar;
    }
}

void threadMainB()
{
    lock(mySync)
    {
        mySync[bar] = foo;
    }
}
3 голосов
/ 12 мая 2009

Вы можете использовать AutoResetEvent.

В следующем примере два метода вызываются разными потоками, и DoSomethingA () будет выполняться и завершаться до запуска DoSomethingB ():

AutoResetEvent resetEvent = new AutoResetEvent(false);

void ThreadWorkerA()
{
    // perform some work
    DoSomethingA();

    // signal the other thread
    resetEvent.Set();
}

void ThreadWorkerB()
{
    // wait for the signal
    resetEvent.WaitOne();

    // perform the new work
    DoSomethingB();
}

Примечание: не забудьте утилизировать AutoResetEvent:)

0 голосов
/ 12 мая 2009

В Java есть что-то, что называется Join. Я подозреваю, что в C # тоже будет предопределенный метод.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...