Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Можно ли использовать один делегат для событий из разных потоков? / 25 сообщений из 28, страница 1 из 2
10.12.2012, 14:42
    #38072530
goalinternet
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
Подскажите пожалуйста, равносильны ли следующие два блока кода, обратить внимание на делегат и смотреть в контексте многопоточного приложения, в первом случае для каждого SocketAsyncEventArgs создается свой делегат, а во втором используется общий, не возникнут ли проблемы с Thread safety:


Код: c#
1.
2.
3.
4.
5.
6.
7.
var pool = new ConcurrentStack<SocketAsyncEventArgs>();
for (int i = 0; i < 1024; i++)
{
    SocketAsyncEventArgs saea = new SocketAsyncEventArgs();
    saea.Completed += new EventHandler<SocketAsyncEventArgs>(completeEvent);
    pool.Push(saea);
}





Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
var pool = new ConcurrentStack<SocketAsyncEventArgs>();
var eventHandler = new EventHandler<SocketAsyncEventArgs>(completeEvent);
for (int i = 0; i < 1024; i++)
{
    SocketAsyncEventArgs saea = new SocketAsyncEventArgs();
    saea.Completed += eventHandler;
    pool.Push(saea);
}



Спасибо за участие и помощь!
...
Рейтинг: 0 / 0
10.12.2012, 16:07
    #38072721
Абсолют
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
В случае с общим может возникнуть ситуация, что один поток, к примеру изменил/обнулил или еще что.
...
Рейтинг: 0 / 0
10.12.2012, 16:23
    #38072768
goalinternet
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
АбсолютВ случае с общим может возникнуть ситуация, что один поток, к примеру изменил/обнулил или еще что.

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

Если это все, то получается подводных камней нет. Еще раз спасибо.
...
Рейтинг: 0 / 0
10.12.2012, 16:34
    #38072802
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
goalinternet,

оба варианты экиваваленты с точки зрения многопоточности, но вариант с отдельным делегатом потратит зря чуть больше памяти (~25 Кб в режиме отладки). Ты в данном случае должен позаботиться чтобы _реализация_ метода completeEvent была безопасной с точки зрения многопоточности.
...
Рейтинг: 0 / 0
10.12.2012, 17:52
    #38072994
goalinternet
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
bazile,

Метод потокобезопасен. Спасибо за ответ.
...
Рейтинг: 0 / 0
14.12.2012, 12:50
    #38079249
goalinternet
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
Не в коем случае никогда не используйте первый случай, такое ощущение что GC высвобождает несколько экземпляров, и я терял сетевые пакеты, после того сделал как описано во втором случае - больше ничего не пропадает.
...
Рейтинг: 0 / 0
14.12.2012, 15:27
    #38079580
goalinternet
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
goalinternetНе в коем случае никогда не используйте первый случай, такое ощущение что GC высвобождает несколько экземпляров, и я терял сетевые пакеты, после того сделал как описано во втором случае - больше ничего не пропадает.

Каюсь я не прав. Обе версии равносильны.
...
Рейтинг: 0 / 0
14.12.2012, 15:56
    #38079638
beg-in-er
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
goalinternetКаюсь я не прав. Обе версии равносильны.ессесна. ну кроме количества памяти , как написал bazile
т.к. делегат это некий указатель на метод. а все методы вызываются с дополнительным параметром - контектс вызова ( типа вызывающи класс)
Код: c#
1.
2.
3.
4.
5.
6.
class MyClass
{
 void Function1(){}
}
//на самом деле вызывается как то так. гляньте дизасм. там всё это видно.
static void Function1(MyClass par1){}
...
Рейтинг: 0 / 0
14.12.2012, 16:03
    #38079660
Lexxxxx
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
beg-in-er...т.к. делегат это некий указатель на метод. а все методы вызываются с дополнительным параметром - контектс вызова ( типа вызывающи класс)
Код: c#
1.
2.
3.
4.
5.
6.
class MyClass
{
 void Function1(){}
}
//на самом деле вызывается как то так. гляньте дизасм. там всё это видно.
static void Function1(MyClass par1){}



А можно подробностей?
...
Рейтинг: 0 / 0
14.12.2012, 18:17
    #38079938
Где-то в степи
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
beg-in-ergoalinternetКаюсь я не прав. Обе версии равносильны.ессесна. ну кроме количества памяти , как написал bazile
т.к. делегат это некий указатель на метод. а все методы вызываются с дополнительным параметром - контектс вызова ( типа вызывающи класс)
Код: c#
1.
2.
3.
4.
5.
6.
class MyClass
{
 void Function1(){}
}
//на самом деле вызывается как то так. гляньте дизасм. там всё это видно.
static void Function1(MyClass par1){}


class сгениерит среда если есть замыкание на внешнею переменную, и то не всегда.
коды равнозначные,
у первого надо учесть только
что среда расставит все по своим местам типа
EventHandler<SocketAsyncEventArgs> completeEvent=-чтото;
saea.Completed += completeEvent;
и размер стеека функции у них должен быть одинаковый.
единственно что не учел товарищ, ( впрочем не видим этот код и эта тема не поднималась) как он будет исповедовать объект
перед смертью, слабыми событиями там даже не пахнет ( я поднял это, если он заговорил о уборщике)
...
Рейтинг: 0 / 0
14.12.2012, 19:16
    #38080037
beg-in-er
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
Lexxxxx
А можно подробностей?
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
        void Function()
        {
            Function2(7);
            Function2(3);
        }

        void Function2(int x)
        {
        }



Function2(7);
00000025 mov ecx,dword ptr [ebp-3Ch]
00000028 mov edx,7
0000002d call FF919DC8
Function2(3);
00000033 mov ecx,dword ptr [ebp-3Ch]
00000036 mov edx,3
0000003b call FF919DC8
ptr [ebp-3Ch] это как бэ адресс класса
...
Рейтинг: 0 / 0
14.12.2012, 21:14
    #38080147
Lexxxxx
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
И все таки я нифига не понял! Получается что можно сослаться на один и тот же экземпляр метода в качестве обработчика события в двух разных потоках и при этом совершенно не нужно заботится о потокобезопасности этого метода?!
...
Рейтинг: 0 / 0
14.12.2012, 21:37
    #38080167
Где-то в степи
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
Lexxxxx,
о потокобезопасности захваченного объекта, надо заботиться, одна из отличительных особенностей делегата, это то что метод
может исолниться когда ему вздумается ( образно) пользователь нажал кнопку по своему разумению? и по этому вся работа с замыканием ложится на Вас.
предположим нажали кнопку, и пошол грид дербаниться ( долго)( грид замыкание) а в это время еще нарисовался делегат с этим же методом, он тоже полез дербанить грид ( в простонародье это называется двухстволка) но там то мы хоть можем договориться куда совать, а с гридом нет, по этому и озвучили эту тему.
хоть и компилятор создает класс обертку для функции под делегат, и включает в этот класс объект замыкание, но при создании этой обертки он инициализирует этот объект обетом снаружи (grid)
...
Рейтинг: 0 / 0
14.12.2012, 22:16
    #38080210
Lexxxxx
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
Где-то в степи,

На сколько я понимаю, если один и тот же метод повесить обработчиком на пару или более событий в разных потоках, может случится одновременный вызов и/или переключение контекста потоков один или более раз, а значит внутри метода с его данными может случится просто фарш. А значит или тело этого метода должно быть полностью обернуто в lock, что приведет к ожиданию других потоков, а значит к потере быстродействия, или просто нужно для каждого потока иметь свой экземпляр метода-обработчика чтобы не иметь потерь при блокировках потоков при одновременном наступлении события в нескольких из них.
Правильно я рассуждаю?
...
Рейтинг: 0 / 0
14.12.2012, 23:27
    #38080281
buser
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
LexxxxxПравильно я рассуждаю? нет.
...
Рейтинг: 0 / 0
14.12.2012, 23:47
    #38080297
Где-то в степи
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
Lexxxxx,
нет конечно Вы же можете инициализировать делегат статическим методом, там то что будет в нутрях изменяться, равнозначно
и можно инициализировать методом экземпляра объекта, каждый поток получит делегат, и при вызове получит метод в первозданном виде, можно зарядить делегат по месту.
вот пример var table = new DataTable(); table.Columns.Add("1"); table.Columns.Add("2"); new Thread(() => table.Rows.Add("asa", "sad")).Start(); я в какой то функции исполнил такой код;
Создал таблицу, зарядил ее колонками, и вызвал поток зарядив его делегатом по месту () => table.Rows.Add("asa", "sad")
в этом делегате я сделал замыкание на таблицу то биш в нее вставляю строку.
я уверен что я вставил 1 строку, но в это время другой поток, проснулся и полез тоже вставлять строку, вот я и в ах..е, как так
я вставил строку, а там уже 2 ((... поаял а не?
зы кстати если посмотреть байт код из примера, там должен класс обертка конкретно создаться, и положиться в стек..
...
Рейтинг: 0 / 0
15.12.2012, 01:02
    #38080332
LR
LR
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
Lexxxxx,

"потокобезопасность" - проблема достаточно деликатная/мутная, ее нельзя решить раз и навсегда какими-то простыми правилами "либо-либо", необходим достаточный уровень понимания того что будет происходить (как будет выполняться код) в каждом конкретном случае... вот частоприводимый по теме простой пример:
Код: 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.
        static void Main(string[] args)
        {
            for (int i = 0; i < 10; i++)
                new Thread(() => Console.Write(i)).Start();

            Thread.Sleep(100);
            Console.WriteLine();

            for (int i = 0; i < 10; i++) {
                int j = i;
                new Thread(() => Console.Write(j)).Start();
            }

            Thread.Sleep(100);
            Console.WriteLine();

            for (int i = 0; i < 10; i++)
                new Thread(ConsoleWrite).Start(i);
            
            Console.ReadKey();
        }
        static void ConsoleWrite(object x)
        {
            Console.Write(x.ToString());
        }
...
Рейтинг: 0 / 0
15.12.2012, 09:38
    #38080407
Lexxxxx
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
Где-то в степи...Создал таблицу, зарядил ее колонками, и вызвал поток зарядив его делегатом по месту () => table.Rows.Add("asa", "sad")
в этом делегате я сделал замыкание на таблицу то биш в нее вставляю строку.
я уверен что я вставил 1 строку, но в это время другой поток, проснулся и полез тоже вставлять строку, вот я и в ах..е, как так
я вставил строку, а там уже 2 ((... поаял а не?..

Как я понял экземпляр таблицы один для всех делегатов во всех потоках?
...
Рейтинг: 0 / 0
15.12.2012, 10:16
    #38080420
Lexxxxx
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
LR,

Не могли бы Вы разъяснить подробно этот пример для неграмотных? Уже не совсем понятно почему в первом цикле выводимые номера дублируются? ) То, что они выводятся не по порядку вроде как объясняется тем, что планировщик задач запускает потоки по своему усмотрению и не обязательно в том порядке, в котором их ему передавали. Но откуда повторения?!
...
Рейтинг: 0 / 0
15.12.2012, 10:53
    #38080427
Где-то в степи
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
LexxxxxГде-то в степи...Создал таблицу, зарядил ее колонками, и вызвал поток зарядив его делегатом по месту () => table.Rows.Add("asa", "sad")
в этом делегате я сделал замыкание на таблицу то биш в нее вставляю строку.
я уверен что я вставил 1 строку, но в это время другой поток, проснулся и полез тоже вставлять строку, вот я и в ах..е, как так
я вставил строку, а там уже 2 ((... поаял а не?..

Как я понял экземпляр таблицы один для всех делегатов во всех потоках?
Ну да, д. это по существу код потока,( мы создаем поток спуская в него делегат, запускаем делегат begininvoke) и естественно
должны рассматривать этот код с позиции потока аки конкурентный доступ, к чему то общему для потоков, или коллизии при исполнении и т.д.
...
Рейтинг: 0 / 0
15.12.2012, 11:10
    #38080431
Lexxxxx
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
Где-то в степиНу да, д. это по существу код потока,( мы создаем поток спуская в него делегат, запускаем делегат begininvoke) и естественно
должны рассматривать этот код с позиции потока аки конкурентный доступ, к чему то общему для потоков, или коллизии при исполнении и т.д.

Ну так я же об этом и говорил, а Вы сказали что я не прав.
А Вы не подскажете ответ на вопрос про дублирующиеся номера?
...
Рейтинг: 0 / 0
15.12.2012, 11:37
    #38080441
Где-то в степи
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
Lexxxxx может случится одновременный вызов и/или переключение контекста потоков один или более раз, а значит внутри метода с его данными может случится просто фарш. А значит или тело этого метода должно быть полностью обернуто в lock,
ну конечно не прав, какие переключения контекстов в методе?
какой фарш может быть с данными метода, если это переменные var в методе, и с внешней средой они не контактируют.
зачем лок на все тело, если тело с внешней средой кода вообще не завязано, равно не завязано, ни с какими объектами окружающих метод, не контактирует и не ссылается на них.
Даже принятия решения лок по отношению к внешней переменной ( переменной замыкания) должно быть обосновано в плане логики.
если например предположить что это какой то аккумулятор типа value, работающий атомарно, зачем там лок вообще нужен?
...
Рейтинг: 0 / 0
15.12.2012, 11:44
    #38080444
Где-то в степи
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
что то я забыл про вопрос.
Есть классика в сети
обязательно почитать всем и разобраться
http://www.rsdn.ru/article/dotnet/CSThreading1.xml
http://www.rsdn.ru/article/dotnet/CSThreading2.xml
...
Рейтинг: 0 / 0
15.12.2012, 11:50
    #38080448
Lexxxxx
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
Где-то в степи,

Да, похоже я неправильно выразился. Каждый поток имеет свой стек, поэтому локальные переменные метода для каждого потока свои. Но вот данные, переданные в метод, тот же экземпляр таблицы, могут быть превращены в месиво, или нет, что конечно же зависит от того, что именно происходит в этом методе.
Прочитать и разобраться конечно можно, но хотелось "проскочить на халяву". ) Там еще и третья часть есть http://rsdn.ru/article/dotnet/Threading_In_C_Sharp_Part_3.xml
...
Рейтинг: 0 / 0
15.12.2012, 13:17
    #38080491
SeVa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли использовать один делегат для событий из разных потоков?
EAP давно уже на свалке вместо него другая модель асинхронности.
Код: 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.
var bufferBlock = new BufferBlock<SocketAsyncEventArgs>>();
var consumer= new ActionBlock<SocketAsyncEventArgs>((x) =>

 {
    Console.WriteLine(x.ToString());

 }, new ExecutionDataflowBlockOptions()

 {

     MaxDegreeOfParallelism = 4

 });

bufferBlock.LinkTo(consumer);


 while(true)
{
    var args = await ReadAsync(socket)
    bufferBlock.Post( args );
}

 static async Task<SocketAsyncEventArgs>  ReadAsync(Socket s) 
{ 
    // Reusable SocketAsyncEventArgs and awaitable wrapper 
    var args = new SocketAsyncEventArgs(); 
    args.SetBuffer(new byte[0x1000], 0, 0x1000); 
    var awaitable = new ReceiveSocketAwaitable(args);

    // Do processing, continually receiving from the socket 
    int bytesRead; 
    while ((bytesRead = await s.ReceiveAsync(awaitable)) > 0) 
    { 
        Console.WriteLine(bytesRead); 
    } 
    return args;
}
}
...
Рейтинг: 0 / 0
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Можно ли использовать один делегат для событий из разных потоков? / 25 сообщений из 28, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]