C # -Потоки и передача родителя ребенку - PullRequest
1 голос
/ 09 июня 2011

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

public class A
{
    public A() 
    { 
        B b = new B(this);
        Thread thread = new Thread(new ThreadStart(b.GO));
    }
    public string DoSomething() { return "Something Done"; }
}

public class B
{
    A _a;
    public B(A a) 
    {
        _a = a;
    }
    public void GO() { _a.DoSomething(); }
}

Исходя из вышесказанного, мне интересно, возникают ли какие-либо соглашения о конфликтах или проблемах, которые возникают, когда вы делаете что-то подобное, плохо это делать?Я знаю, что, безусловно, возникают некоторые проблемы с безопасностью потоков.Но мой общий вопрос в порядке, делает ли это некоторые другие проблемы?Как бы я обновил значения в главном потоке?Причина, по которой я хочу, чтобы он был отдельным, заключается в том, что в классе B имеется таймер (не показан в коде), который, когда он заканчивается, делает что-то, а затем сообщает классу, что он закончил, сбрасывает таймер и возвращается в спящий режим до тех пор, пока таймерснова иссякает, как мне поступить иначе?

~ С уважением,

Генрих

Ответы [ 2 ]

3 голосов
/ 09 июня 2011

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

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

Я бы порекомендовал следующую онлайн книгу: http://www.albahari.com/threading/

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

Сайт, на который я ссылался, содержит много разных методов сигнализации. Выберите самое простое для ваших нужд. Мне нужно больше информации о ваших точных требованиях, чтобы выбрать один для вас.

1 голос
/ 09 июня 2011

Еще один способ справиться с тем, что вы делаете, - для B вызвать событие, а для A - обработать событие.Таким образом, вам не нужно передавать A в B. Я не знаю, какова ваша реальная структура, но допустим, что функция потока B делает что-то более сложное, и A реализует IDisposable.Что происходит, если A удаляется до того, как B доходит до того, что вызывает метод для A. Для меня более чистый способ справиться с этой ситуацией - это вызвать B и вызвать событие A.

public class A
{
    B _b;

    public A()
    {
        _b = new B();
        _b.DidSomething += HandleDidSomething;
    }

    private void HandleDidSomething(object source, EventArgs e)
    {
        // Handle the B did something case
    }

    public void WaitForBToFinish() { _b.DoneDoingThings.WaitOne(); }
}

public class B
{
    Event EventHandler DidSomething;

    ManualResetEvent DoneDoingThings = new ManualResetEvent(false);

    public B() {}

    public void StartDoingThings()
    {
        new Thread(DoThings).Start();
    }

    private void DoThings()
    {
         for (int i=0; i < 10; i++)
         {
             Thread.Sleep(1000);
             OnDidSomething(new EventArgs());
         }

         DoneDoingThings.Set();
    }

    private void OnDidSomething(EventArgs e)
    {
         if (DidSomething != null)
         {
              DidSomething(e);
         }
    }    
 }

Примечание - Вы должны реализовать IDisposable в классе B и избавиться от ManualResetEvent, я просто ленив, чтобы сделать все это для примера кода, и просто хотел дать вам представление об использовании событий, чтобы сигнализировать о работе.

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