Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Многопоточность и доступ к разделяемому ресурсу 
:(
    Опции темы
botusai
Дата 24.9.2007, 13:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 24.9.2007

Репутация: нет
Всего: нет



Вот такая задача: у меня в программе есть много потоков и каждый должен вывести свои аргументы в (внимание!!) TextBox на форме, подскажите плиз как это делать. пробовал и Mutex  и lock , ничего не помогло. Вот код, правда уже местами переделанный, но лишнее убрано.

Код

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace Threads
{
    public class Function
    {
        private static System.Object LOCK = new System.Object();
        private static Mutex mut;

        public double[] Answers;

        public void Allocate(int size)
        {
            Answers = new double[size];
        }

        public ManualResetEvent _event;
        public double _arg;
        public int index;
        public double _answer;

        public Function()
        {
            mut = new Mutex();
        }

        public Function(double arg, ManualResetEvent Event)
        {
            _arg = arg;
            _event = Event;
        }


        public void FunctionWrapper2()
        {
            Answers[index] = F1(_arg);
           //mut.WaitOne();
            lock(LOCK)
            {
                Program._Forms._Form1.tbAnswers.Text += "111" + Environment.NewLine;
            }
            //mut.ReleaseMutex();

        }
        public double F1(double x)
        {
            //return x * x * x - Math.Sin(x) + x * x - x;                        
            //return Math.Sin(x)+Math.Cos(x)+5;
            return x * x;
        }
    }

    public class Calculator
    {
        double _answer;

        public Calculator()
        {
            LocalFunction = new Function();
        }

        public double ThreadedIntegral2(double a, double b, double h)
        {
            double sum = 0;
            int count = (int)((b - a) / h) + 1;
            int MAXTHREADS = 64;
            
            Thread[] threads = new Thread[count];

            Function f = new Function();
            f.Allocate(MAXTHREADS);

            for (int k = 0; k < count / MAXTHREADS + 1; k++)
            {
                int localcount = Math.Min(MAXTHREADS, count);

                for (int i = 0; i < localcount; i++)
                {               
                    f.index = i;
                    f._arg = a + i * h + h / 2 + MAXTHREADS * k * h;
                    threads[k * MAXTHREADS + i] = new Thread(new ThreadStart(f.FunctionWrapper2));
                    threads[k * MAXTHREADS + i].Start();
                }                                               

                for (int i = 0; i < localcount; i++)
                {
                    threads[k * MAXTHREADS + i].Join();
                }
                for (int i = 0; i < localcount; i++)
                {
                    sum += f.Answers[i];
                }
                count -= MAXTHREADS;
            }

            return sum * h;
        }

        public void ThreadedIntegralWrapper(Object data)
        {
            double [] args = (double[]) data;
            _answer = ThreadedIntegral2(args[0], args[1], args[2]);
            _event.Set();
        }

        public double ThreadedIntegralPrecise(double a, double b, double e)
        {
            double step = b-a;

            if (step < e)
            {
                return step * LocalFunction.F1(a);
            }
                        
            Calculator Calc1 = new Calculator();
            Calculator Calc2 = new Calculator();
            double ans1 = Calc1.ThreadedIntegral2(a, b, step);
            double ans2 = Calc2.ThreadedIntegral2(a, b, step/2);

            if (Math.Abs(ans1 - ans2) < e * step / Program.Length)
            {
                return 0.5 * (ans1 + ans2);
            }

            return ThreadedIntegralPrecise(a, a + step / 2, e) +
                   ThreadedIntegralPrecise(a + step / 2, b, e);
        }

    }
}


Это сообщение отредактировал(а) botusai - 25.9.2007, 17:41
PM MAIL   Вверх
0000
Дата 24.9.2007, 15:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 208
Регистрация: 11.7.2006
Где: Нижний Новгород

Репутация: 2
Всего: 5



к примеру у тебя есть Form1 form;

объявляешь делегат 

Код

public delegate void AppendTextDelegate(string text);


есть метод, который изменяет твой контрол
Код

private void privateAppendText(string text)
{
    this.textBox1.Text = text;
}


а так же есть открытый метод, доступный из других потоков (там можно, например, реакцию на событие использовать, если хочешь промежуточные результаты давать или еще что-нибудь)
Код

public void publicAppendText(string text)
{
     this.textBox1.BeginInvoke(new AppendTextDelegate(this.privateAppendText), new object [] { text});
}

теперь у тебя запущен отдельный поток, который обновляет данные в текстбоксе..
я правильно понял что надо было??

ЗЫ. используй подсветку кода - удобнее 

Это сообщение отредактировал(а) 0000 - 24.9.2007, 15:22
PM MAIL ICQ   Вверх
botusai
Дата 24.9.2007, 16:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 24.9.2007

Репутация: нет
Всего: нет



вооюще-то я хотел спросить про создание критической секции, так чтобы в каждый момент времени только какой-то один поток имел доступ к текстбоксу, т.е как бы внутри потока находится метод изменения текста в текстбоксе
PM MAIL   Вверх
0000
Дата 24.9.2007, 16:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 208
Регистрация: 11.7.2006
Где: Нижний Новгород

Репутация: 2
Всего: 5



так в изменении текстбокса можешь его лочить...
а внутри потока ты вызываешь publicAppendText...
или делегат на него, если до формы далеко =)

а еще лучше события.. Calculator.OnPerform..обработчик его в форму и там доступ к текстбоксу

Это сообщение отредактировал(а) 0000 - 24.9.2007, 16:27
PM MAIL ICQ   Вверх
zaver
Дата 24.9.2007, 17:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 204
Регистрация: 15.8.2005

Репутация: нет
Всего: 3



Блин! прикрепите тему про Invoke! каждая пятая тема про это.
-------
а сори, увидел, уже прикреплено smile 

Это сообщение отредактировал(а) zaver - 24.9.2007, 17:37
PM MAIL WWW ICQ Skype YIM MSN   Вверх
tol05
Дата 24.9.2007, 22:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



Цитата(botusai @  24.9.2007,  16:05 Найти цитируемый пост)
вооюще-то я хотел спросить про создание критической секции, так чтобы в каждый момент времени только какой-то один поток имел доступ к текстбоксу, т.е как бы внутри потока находится метод изменения текста в текстбоксе 
Цитата(0000 @  24.9.2007,  16:25 Найти цитируемый пост)
так в изменении текстбокса можешь его лочить...

о чем вы, господа девелоперы? Кого от кого лочить???  smile 

Почитайте мануалы, Invoke посылает команду на вызов метода В ПОТОК КОНТРОЛА. 
Сколько бы потоков не вызывало Invoke "для обновления текстбокса"  smile все эти вызовы просто становятся в очередь сообщений потока и будут обработаны последовательно! (т.к. обновление может быть произведено только одним потоком (создателем контрола)).

Именно этим методом Invoke() как раз и гарантируется потокозащищенность винформс-контролов.
Цитата

In addition to the InvokeRequired property, there are four methods on a control that are thread safe: Invoke, BeginInvoke, EndInvoke, and CreateGraphics. For all other method calls, you should use one of the invoke methods to marshal the call to the control's thread.

:(


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
botusai
Дата 25.9.2007, 11:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 24.9.2007

Репутация: нет
Всего: нет



0000 большое тебе спасибо

Это сообщение отредактировал(а) botusai - 25.9.2007, 11:10
PM MAIL   Вверх
0000
Дата 25.9.2007, 11:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 208
Регистрация: 11.7.2006
Где: Нижний Новгород

Репутация: 2
Всего: 5



Цитата(tol05 @ 24.9.2007,  22:23)
о чем вы, господа девелоперы? Кого от кого лочить???  smile 

Почитайте мануалы, Invoke посылает команду на вызов метода В ПОТОК КОНТРОЛА. 
Сколько бы потоков не вызывало Invoke "для обновления текстбокса"  smile все эти вызовы просто становятся в очередь сообщений потока и будут обработаны последовательно! (т.к. обновление может быть произведено только одним потоком (создателем контрола)).

Именно этим методом Invoke() как раз и гарантируется потокозащищенность винформс-контролов.
:(


контролом управляет только поток, его создающий...угу...
тогда зачем различать BeginInvoke и Invoke

Код

Control.BeginInvoke - Выполняет делегат асинхронно на том потоке, на котором был создан основной дескриптор элемента управления.


Код

Control.Invoke - Выполняет делегат в том потоке, которому принадлежит основной дескриптор окна элемента управления.


тогда какая разница между методами, если контрол создается в главном потоке?


PM MAIL ICQ   Вверх
tol05
Дата 25.9.2007, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



рефлектор есть? 
Код

[EditorBrowsable(EditorBrowsableState.Advanced)]
public IAsyncResult BeginInvoke(Delegate method, params object[] args)
{
    using (MultithreadSafeCallScope scope = new MultithreadSafeCallScope())
    {
        return (IAsyncResult) this.FindMarshalingControl().MarshaledInvoke(this, method, args, false);
    }
}

public object Invoke(Delegate method, params object[] args)
{
    using (MultithreadSafeCallScope scope = new MultithreadSafeCallScope())
    {
        return this.FindMarshalingControl().MarshaledInvoke(this, method, args, true);
    }
}


как мы видим, отличие в последнем параметре. Смотрим что за параметр
Код

private object MarshaledInvoke(Control caller, Delegate method, object[] args, bool synchronous)
{
    int num;
    ...
    ExecutionContext executionContext = null;
    if (!flag)
    {
        executionContext = ExecutionContext.Capture();
    }

    ThreadMethodEntry entry = new ThreadMethodEntry(caller, method, args, synchronous, executionContext);
//Если acинхронный вызов BeginInvoke
//возвращаем вызывающему потоку ThreadMethodEntry (наследника IAsyncResult), пусть сам проверяет окончание выполнения делегата
    if (!synchronous)
    {
        return entry;
    }
//Если cинхронный вызов Invoke
//ждем пока выполнится делегат и только потом возвращаем результат вызывающему потоку
    if (!entry.IsCompleted)
    {
        this.WaitForWaitHandle(entry.AsyncWaitHandle); 
    }
    ...
    return entry.retVal;
}

Таким образом, разница указана уже в названии методов... 
P.S.
Invoke посылает запрос в поток контрола и курит, останавливаясь и ожидая окончания его выполнения
BeginInvoke  посылает запрос в поток контрола и продолжает выполнять свой код

Это сообщение отредактировал(а) tol05 - 25.9.2007, 12:50


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
0000
Дата 25.9.2007, 14:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 208
Регистрация: 11.7.2006
Где: Нижний Новгород

Репутация: 2
Всего: 5



ага..то есть поток контрола считаем отдельно от главного...вот тут у меня непонятки и были..все, ясно, снекс 
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0807 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.