Регистрация Главная Сообщество
Сообщения за день Справка Регистрация
Навигация
Zhyk.org LIVE! Реклама на Zhyk.org Правила Форума Награды и достижения Доска "почета"

Ответ
 
Опции темы
Старый 16.11.2012, 05:33   #1
 Сержант
Аватар для Yukikaze
 
Yukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядом
Регистрация: 01.10.2011
Сообщений: 128
Популярность: 5723
Сказал(а) спасибо: 25
Поблагодарили 174 раз(а) в 105 сообщениях
 
По умолчанию Программистов параллельных тред

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

Meet the Task<T, TResult>
Данный класс очень прост в использовании, достаточно создать экземпляр с генерик параметрами типов входных и выходных данных.
Пример:
Код:
Task<int, string> task = new Task<int, string>(i => i.ToString("X2"), 57005);
int в треугольных скобках обозначает тип входящих данных, в примере это число 57005, а string это тип возвращаемый функцией переданной в первый параметр.
Теперь можно запустить выполнение методом Execute():
Код:
Task<int, string> task = new Task<int, string>(i => i.ToString("X2"), 57005);
task.Execute();
Если вы запустили вышеприведенные строки то наверное уже заметили, что нихрена не происходит, это все потому что метод выполнился асинхронно и по окончанию вычислений спровоцировал событие, что-бы увидеть результат нужно подписаться на это событие.
Пример:
Код:
static void Main(string[] args)
{
    Task<int, string> task = new Task<int, string>(i => i.ToString("X2"), 57005);
    task.Complete += TaskComplete;
    task.Execute();
    Console.ReadKey(true);
}

private static void TaskComplete(object sender, string s)
{
    Thread.Sleep(3000);
    Console.WriteLine("0x" + s);
}
Теперь запустив приложение, через 3 секунды, мы увидим результат - надпись 0xDEAD. При этом приложение не повиснет на время выполнения кода.

Пример:
Код:
static void Main(string[] args)
{
    Task<string, bool>(Func, "login1;password666");
    task.Complete += TaskComplete;
    task.Execute();
    Console.ReadKey(true);
}

private static void TaskComplete(object sender, bool b)
{
    var loginpassword = ((Task<string, bool>) sender).Argument;
    Console.WriteLine("User: {0} Login successful: {1}", loginpassword, b);
}

private static bool Func(string s)
{
    string[] pair = s.Split(';');
    WebClient client = new WebClient();
    string page = client.DownloadString(string.Format("http://www.example.com/login?login={0}&password={1}", pair[0], pair[1]));
    return page.Contains("Login successful");
}
TaskQueue<T, TResult> в догонку
На вход подаем коллекцию тасков, подписываемся на событие Complete, задаем кол-во потоков и запускаем.
Пример:
Код:
static void Main()
{
    List<Task<string, bool>> t = new List<Task<string, bool>>();
    for (int i = 0; i < 100; i++)
    {
        Task<string, bool> temp = new Task<string, bool>(Func, "login;password" + i);
        t.Add(temp);
    }
    TaskQueue<string, bool> h = new TaskQueue<string, bool>(t);
    h.Complete += TaskComplete;
    h.ThreadLimit = 4;
    h.Begin();
    Console.ReadKey(true);
}

private static void TaskComplete(object sender, bool b)
{
    var loginpassword = ((Task<string, bool>) sender).Argument;
    Console.WriteLine("User: {0} Login successful: {1}", loginpassword, b);
}

private static bool Func(string s)
{
    string[] pair = s.Split(';');
    WebClient client = new WebClient();
    string page = client.DownloadString(string.Format("http://www.example.com/login?login={0}&password={1}", pair[0], pair[1]));
    return page.Contains("Login successful");
}
Пользуйтесь на здоровье, добра вам

Upadate #1
AsyncTask - безопасное выполнение в STA потоке
Код:
delegate TResult ThreadStart<in T, out TResult>(T arg);
class AsyncTask<T, TResult>
{
    public event EventHandler<ExecuteCompletedEventArgs<TResult>> Complete;

    public bool IsBusy { get; private set; }
    public ThreadStart<T, TResult> Handler
    {
        get { return _threadStart; } 
        set { _threadStart = value; }
    }

    private ThreadStart<T, TResult> _threadStart;
    private readonly SendOrPostCallback _completed;
    private AsyncOperation _asyncOperation;

    public AsyncTask(ThreadStart<T, TResult> func)
    {
        _threadStart = func;
        _completed = AsyncOperationCompleted;
    }

    private void AsyncOperationCompleted(object state)
    {
        IsBusy = false;
        OnComplete((ExecuteCompletedEventArgs<TResult>) state);
    }

    public bool Start(T arg)
    {
        if (IsBusy) return false;
        IsBusy = true;
        _asyncOperation = AsyncOperationManager.CreateOperation(arg);
        _threadStart.BeginInvoke(arg, Callback, this);
        return true;
    }

    private void Callback(IAsyncResult ar)
    {
        TResult result = _threadStart.EndInvoke(ar);
        ExecuteCompletedEventArgs<TResult> e = new ExecuteCompletedEventArgs<TResult>(result);
        _asyncOperation.PostOperationCompleted(_completed, e);
    }

    protected virtual void OnComplete(ExecuteCompletedEventArgs<TResult> e)
    {
        EventHandler<ExecuteCompletedEventArgs<TResult>> handler = Complete;
        if (handler != null) handler(this, e);
    }
}

class ExecuteEventArgs<T, TResult> : EventArgs
{
    public T Argument { get; private set; }
    public TResult Result { get; set; }
    public ExecuteEventArgs(T arg)
    {
        this.Argument = arg;
    }
}

public sealed class ExecuteCompletedEventArgs<T> : EventArgs
{
    public T Result { get; private set; }
    public ExecuteCompletedEventArgs(T arg)
    {
        this.Result = arg;
    }
}
________________
Talk is cheap. Show me the code
— Linus Torvalds

Последний раз редактировалось Yukikaze; 24.03.2013 в 21:34.
  Ответить с цитированием
4 пользователя(ей) сказали cпасибо:
крайслер (16.11.2012), Sinyss (16.11.2012), the-boxi (29.11.2012), warl0ck (16.11.2012)
Старый 16.11.2012, 11:28   #2
 Старший сержант
Аватар для Sinyss
 
Sinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака Норриса
Регистрация: 29.07.2011
Сообщений: 197
Популярность: 8989
Сказал(а) спасибо: 45
Поблагодарили 175 раз(а) в 139 сообщениях
Отправить сообщение для Sinyss с помощью Skype™
 
По умолчанию Re: Программистов параллельных тред

всего 1 поток задержался, рандом был благосклонен
к TaskComplete надо отдельно потокобезопасность прикручивать или она гарантируется таском?
  Ответить с цитированием
Старый 16.11.2012, 14:31   #3
Заблокирован
 Рыцарь-капитан
Аватар для warl0ck
 
warl0ck сломал счётчик популярности :(warl0ck сломал счётчик популярности :(warl0ck сломал счётчик популярности :(warl0ck сломал счётчик популярности :(warl0ck сломал счётчик популярности :(warl0ck сломал счётчик популярности :(warl0ck сломал счётчик популярности :(warl0ck сломал счётчик популярности :(warl0ck сломал счётчик популярности :(warl0ck сломал счётчик популярности :(warl0ck сломал счётчик популярности :(
Регистрация: 29.01.2010
Сообщений: 547
Популярность: 41279
Сказал(а) спасибо: 692
Поблагодарили 2,270 раз(а) в 1,035 сообщениях
 
По умолчанию Re: Программистов параллельных тред

спасибо, хороший класс. надо бы сохранить в блокнотик, что-бы потом с памяти не писать.
  Ответить с цитированием
Старый 16.11.2012, 16:54   #4
 Сержант
Аватар для Yukikaze
 
Yukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядом
Регистрация: 01.10.2011
Сообщений: 128
Популярность: 5723
Сказал(а) спасибо: 25
Поблагодарили 174 раз(а) в 105 сообщениях
 
По умолчанию Re: Программистов параллельных тред

Цитата:
Сообщение от SinyssПосмотреть сообщение
потокобезопасность прикручивать или она гарантируется таском?

Таск не может быть потокобезопасным, так же как не может быть и не безопасным, это то же самое, что спросить - этот поток потокобезопасен? Класс Таск это обертка над потоком, по этому использование метод инвокера обязательно из за небезопасности контролов и формы

Добавлено через 4 часа 36 минут
Всерьез задумался над тем, как все таки BackgroundWorker вызывает событие в STAThread не спровоцировал исключение, в общем покопался в сорсах и узнал пару интересных вещей. Результат в первом посте.

Если в кратце то асинхронное выполнение проходит через экземпляр класса AsyncOperation который в свою очередь перенаправляет выполнение в главный поток
________________
Talk is cheap. Show me the code
— Linus Torvalds

Последний раз редактировалось Yukikaze; 16.11.2012 в 21:30. Причина: Добавлено сообщение
  Ответить с цитированием
Старый 18.11.2012, 02:06   #5
 Старший сержант
Аватар для Sinyss
 
Sinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака Норриса
Регистрация: 29.07.2011
Сообщений: 197
Популярность: 8989
Сказал(а) спасибо: 45
Поблагодарили 175 раз(а) в 139 сообщениях
Отправить сообщение для Sinyss с помощью Skype™
 
По умолчанию Re: Программистов параллельных тред

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

PS: О, напишу цикл статей про паттерны и где их надо использовать...

Последний раз редактировалось Sinyss; 18.11.2012 в 02:10.
  Ответить с цитированием
Старый 18.11.2012, 02:19   #6
 Сержант
Аватар для Yukikaze
 
Yukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядом
Регистрация: 01.10.2011
Сообщений: 128
Популярность: 5723
Сказал(а) спасибо: 25
Поблагодарили 174 раз(а) в 105 сообщениях
 
По умолчанию Re: Программистов параллельных тред

Куда же еще больше упрощать, это же и так максимально упрощенный генерик бекграундворкер с некоторыми модификациями.
ЗЫ Как по мне использование шаблонов это хорошая практика для предотвращения постоянного анбоксинга при касте <тип> <-> object <-> <тип>
________________
Talk is cheap. Show me the code
— Linus Torvalds
  Ответить с цитированием
Старый 18.11.2012, 02:24   #7
 Старший сержант
Аватар для Sinyss
 
Sinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака Норриса
Регистрация: 29.07.2011
Сообщений: 197
Популярность: 8989
Сказал(а) спасибо: 45
Поблагодарили 175 раз(а) в 139 сообщениях
Отправить сообщение для Sinyss с помощью Skype™
 
По умолчанию Re: Программистов параллельных тред

Цитата:
Сообщение от YukikazeПосмотреть сообщение
Куда же еще больше упрощать, это же и так максимально упрощенный генерик бекграундворкер с некоторыми модификациями.

А ведь можно было наследовать от него и дописать нужные реализации событий, ну и добавить в нужном моменте вызов события ReportProgress... по сути он будет всегда в одном и том же месте...
  Ответить с цитированием
Старый 18.11.2012, 02:40   #8
 Сержант
Аватар для Yukikaze
 
Yukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядом
Регистрация: 01.10.2011
Сообщений: 128
Популярность: 5723
Сказал(а) спасибо: 25
Поблагодарили 174 раз(а) в 105 сообщениях
 
По умолчанию Re: Программистов параллельных тред

Sinyss, ну это невозможно как минимум потому, что нельзя перегрузить события, а это убивает всю задумку
________________
Talk is cheap. Show me the code
— Linus Torvalds
  Ответить с цитированием
Старый 18.11.2012, 03:10   #9
 Старший сержант
Аватар для Sinyss
 
Sinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака Норриса
Регистрация: 29.07.2011
Сообщений: 197
Популярность: 8989
Сказал(а) спасибо: 45
Поблагодарили 175 раз(а) в 139 сообщениях
Отправить сообщение для Sinyss с помощью Skype™
 
По умолчанию Re: Программистов параллельных тред

Цитата:
Сообщение от YukikazeПосмотреть сообщение
Sinyss, ну это невозможно как минимум потому, что нельзя перегрузить события, а это убивает всю задумку

Почему нельзя перезагрузить события? Там все нужные функции virtual, да и конкретную реализацию нужного события мы всегда можем переписать на нужный нам метод...

backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler( backgroundWorker1_ProgressChanged);
// какие то действия
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler( backgroundWorker1_New_ProgressChanged);

Вот мы и перегрузили событие...

ИМХО событие это просто ссылка на функцию, которую мы можем в любой момент заменить на новую реализацию не удаляя старую

Последний раз редактировалось Sinyss; 18.11.2012 в 03:18.
  Ответить с цитированием
Старый 18.11.2012, 03:46   #10
 Сержант
Аватар для Yukikaze
 
Yukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядомYukikaze в состоянии испепелить взглядом
Регистрация: 01.10.2011
Сообщений: 128
Популярность: 5723
Сказал(а) спасибо: 25
Поблагодарили 174 раз(а) в 105 сообщениях
 
По умолчанию Re: Программистов параллельных тред

Sinyss, вообще-то в приведенном примере ты подписался на событие, а виртуалом отмечены только евент инвокаторы которые практически всегда одинаковые, с заглушкой от NullReferenceExeption'а
Код:
protected virtual void OnComplete(EventArgs e)
{
    SomeDelegate handler = Complete;
    if (handler != null) handler(this, e);
}
А вот переписать событие это уже другая ситуация, например имеем
Код:
delegate void SomeDelegate(object sender, EventArgs e);
следовательно событие будет выглядеть так
Код:
event SomeDelegate SomeEvent;
а делегат SomeDeleagte мне по какой то причине не подходит, например потому, что принимает в параметр только EventArgs, а мне нужен int.

В общем возможно добавить только новые события и вызывать их старыми инвокаторами.
Короче с таким же успехом можно сказать : "Используй ThreadPool вместо BackgroundWorker'а зачем усложнять" ведь BackgroundWorker это обертка над Delegate.BeginInvoke который в свою очередь передает выполнение функции в ThreadPool. ASyncTask и BackgroundWorker используют разные реализации одних и тех же действий.
________________
Talk is cheap. Show me the code
— Linus Torvalds
  Ответить с цитированием
Старый 18.11.2012, 13:46   #11
 Старший сержант
Аватар для Sinyss
 
Sinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака Норриса
Регистрация: 29.07.2011
Сообщений: 197
Популярность: 8989
Сказал(а) спасибо: 45
Поблагодарили 175 раз(а) в 139 сообщениях
Отправить сообщение для Sinyss с помощью Skype™
 
По умолчанию Re: Программистов параллельных тред

Ну в принципе можно написать myEventArg наследуемый от EventArgs и передавать его через приведение типов... но да, это будет не элегантно...
  Ответить с цитированием
Старый 17.04.2014, 01:07   #12
Читер-спонсор
 Сержант
Аватар для lcd1232
 
lcd1232 скоро будет известенlcd1232 скоро будет известенlcd1232 скоро будет известенlcd1232 скоро будет известен
Регистрация: 12.09.2010
Сообщений: 165
Популярность: 375
Сказал(а) спасибо: 70
Поблагодарили 39 раз(а) в 25 сообщениях
Отправить сообщение для lcd1232 с помощью ICQ Отправить сообщение для lcd1232 с помощью Skype™
 
По умолчанию Re: Программистов параллельных тред

А что если у меня функция требует несколько входных параметров? Как быть?
________________
[Ссылки могут видеть только зарегистрированные пользователи. ]
  Ответить с цитированием
Старый 17.04.2014, 05:15   #13
Читер-спонсор
 Рыцарь-защитник
Аватар для Hermein
 
Hermein сломал счётчик популярности :(Hermein сломал счётчик популярности :(Hermein сломал счётчик популярности :(Hermein сломал счётчик популярности :(Hermein сломал счётчик популярности :(Hermein сломал счётчик популярности :(Hermein сломал счётчик популярности :(Hermein сломал счётчик популярности :(Hermein сломал счётчик популярности :(Hermein сломал счётчик популярности :(Hermein сломал счётчик популярности :(
Регистрация: 14.01.2011
Сообщений: 633
Популярность: 28087
Золото Zhyk.Ru: 1
Сказал(а) спасибо: 90
Поблагодарили 717 раз(а) в 374 сообщениях
Отправить сообщение для Hermein с помощью ICQ Отправить сообщение для Hermein с помощью Skype™
 
По умолчанию Re: Программистов параллельных тред

Цитата:
функция требует несколько входных параметров?

Я лично использую лямбды в таких случаях.
ps: Экспериментировал со всеми вариациями распараллеливания и работает лучше всех Parallel, результаты тестов привести не смогу, ибо делались специфические с огромными математическими задачами(от 300кк итераций), но, возможно для небольших задач подойдут Thread или Task
  Ответить с цитированием
Ответ


Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Премиумные танки: общий сравнительно-познавальный тред умненький Общение и обсуждение по World of Tanks 2 24.08.2011 17:32
для программистов heyboo Общение и обсуждение (Тюряга ВК) 5 07.06.2011 03:33
[Уязвимость] Официальный Тред Бобра™ DELETE ME!!111 Треп 4 21.11.2009 18:48

Заявление об ответственности / Список мошенников

Часовой пояс GMT +4, время: 12:33.

Пишите нам: [email protected]
Copyright © 2024 vBulletin Solutions, Inc.
Translate: zCarot. Webdesign by DevArt (Fox)
G-gaMe! Team production | Since 2008
Hosted by GShost.net