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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Получение данных из потока 
V
    Опции темы
arsenium
Дата 1.6.2011, 18:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Здравствуйте! Подскажите куда копать, разбираюсь с потоками в c#. 
И возник такой вопрос, к примеру есть метод читающий обычный txt файл в переменную, и это чтение происходит в отдельном потоке, как получить доступ к этой переменной из главного потока?

К примеру метод:
Код

public class Test
    {
      public string FileText;
      public void ReadFile()
        {
         //читаем файл в переменную string.
         FileText=...
        }
    }

И вызываем этот метод в потоке:

Код

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

private void button1_Click(object sender, EventArgs e)
        {
         Test TestRead = new Test();
         new Thread(TestRead.ReadFile).Start();
         TextBox1.Text=...
        }
}

Вот к примеру, если такой код, и мне нужно в классе Form1 после выполнения потока достать то, что записалось в переменную FileText и вывести это ее в TextBox1 на форме.
PM MAIL   Вверх
KuMa1104
Дата 1.6.2011, 20:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 541
Регистрация: 16.4.2009
Где: Ростов-на-Дону

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



ну как самый простой вариант хранить данные в какой то переменной и передать. 
Код

public string ReadFile()
        {
         string output;
         //читаем файл в переменную string.
         output=...

         return output;
        }


В форме сделать отдельную ф-ию
Код

void DoWork()
{
       string FileText =  TestRead.ReadFile();

        TextBox1.Invoke((MethodInvoker)delegate{TextBox1.Text = FileText }) //анонимный делегат
}


вызываеш ф-ию
Код

private void button1_Click(object sender, EventArgs e)
        {
         Test TestRead = new Test();
         new Thread(DoWork).Start();
        }



Это сообщение отредактировал(а) KuMa1104 - 1.6.2011, 20:51


--------------------
Галактика – суровая штука. Чтобы в ней выжить, надо знать, где твое полотенце.

Время - штука относительная... а время обеда - ещё более относительная
PM MAIL   Вверх
KuMa1104
Дата 1.6.2011, 20:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 541
Регистрация: 16.4.2009
Где: Ростов-на-Дону

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



А вообще нафиг отделбную ф-ию её тоже в делегат пихай)


--------------------
Галактика – суровая штука. Чтобы в ней выжить, надо знать, где твое полотенце.

Время - штука относительная... а время обеда - ещё более относительная
PM MAIL   Вверх
Dennnis
Дата 2.6.2011, 05:27 (ссылка)    | (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



В приведенном тобой примере доступ к считанным данным можно получить так:
Код

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

private void button1_Click(object sender, EventArgs e)
        {
         Test TestRead = new Test();
         new Thread(TestRead.ReadFile).Start();
         Thread.Sleep(100); //Подождать пока считаются данные
         TextBox1.Text=TestRead.FileText;
        }
}

 smile 

Это сообщение отредактировал(а) Dennnis - 2.6.2011, 05:28
--------------------
Get Rich or Die Tryin'
PM   Вверх
Экскалупатор
Дата 2.6.2011, 08:51 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

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



Dennnis, а какой в этом смысл? зачем запускать чтение в отдельном потоке и ждать пока оно закончится? параллельные потоки нужны тогда когда нельзя ждать, и нужно что бы задача выполнилась в фоне пока приложение выполняет какую то другую задачу. а у тебя получилось что приложение запускает поток, а потом просто ждет пока поток закончит читать. к тому же ты уверен что отведенного тобой времени хватит на то что бы закончить чтение? пока что может и хватит, а в будущем?
PM MAIL ICQ   Вверх
arsenium
Дата 2.6.2011, 10:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



KuMa1104, хм, спасибо большое.
но тут я так понял сразу в textBox результат выводит, а сильно усложнится если сначала присвоить результат промежуточной переменной TempText, а только потом присвоить ее TextBox1.Text, так ведь по идее можно?

Код

void DoWork()
{
       string TempText="";
       string FileText =  TestRead.ReadFile();

        //TextBox1.Invoke((MethodInvoker)delegate{TextBox1.Text = FileText; });
        //TempText

        //какие-то действия с TempText.
        TextBox1.Text=TempText;
}


Цитата

А вообще нафиг отделбную ф-ию её тоже в делегат пихай)

А тут немного не понял...
PM MAIL   Вверх
jonie
Дата 2.6.2011, 12:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

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



лучше вместо создания Thread-а (как в примерах выше) использовать либо BackgroundWorker либо Task


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
KuMa1104
Дата 2.6.2011, 12:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 541
Регистрация: 16.4.2009
Где: Ростов-на-Дону

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



Цитата(arsenium @  2.6.2011,  10:50 Найти цитируемый пост)
так ведь по идее можно?

так по идее плохо. У тебя TextBox1 был создан в другом потоке. это crossthread. В debug будет вообще кидать exception.

TextBox1.Invoke // почитай он как раз и вызывает поток которому принадлежит.

разберись с этим это очень полезная штука. и про BackgroundWorker тоже почитай .jonie прав это оч сильная штука.



--------------------
Галактика – суровая штука. Чтобы в ней выжить, надо знать, где твое полотенце.

Время - штука относительная... а время обеда - ещё более относительная
PM MAIL   Вверх
Dennnis
Дата 2.6.2011, 14:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(Экскалупатор @  2.6.2011,  08:51 Найти цитируемый пост)
Dennnis, а какой в этом смысл? зачем запускать чтение в отдельном потоке и ждать пока оно закончится? параллельные потоки нужны тогда когда нельзя ждать, и нужно что бы задача выполнилась в фоне пока приложение выполняет какую то другую задачу. а у тебя получилось что приложение запускает поток, а потом просто ждет пока поток закончит читать. к тому же ты уверен что отведенного тобой времени хватит на то что бы закончить чтение? пока что может и хватит, а в будущем? 

Нету смысле) Я просто написал как получить доступ к данным записанных другим потокомsmile

Это сообщение отредактировал(а) Dennnis - 2.6.2011, 14:10
--------------------
Get Rich or Die Tryin'
PM   Вверх
Экскалупатор
Дата 2.6.2011, 17:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

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



Dennnis, а ждать зачем?
PM MAIL ICQ   Вверх
arsenium
Дата 2.6.2011, 22:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(jonie @  2.6.2011,  12:11 Найти цитируемый пост)
лучше вместо создания Thread-а (как в примерах выше) использовать либо BackgroundWorker либо Task

А немог бы кто-нибудь набрасать пример для моего случая с использованием BackgroundWorker? и объяснить разницу с использованием Thread?
PM MAIL   Вверх
Dennnis
Дата 3.6.2011, 05:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(Экскалупатор @  2.6.2011,  17:58 Найти цитируемый пост)
Dennnis, а ждать зачем? 

Если не ждать, то можно получить некорректные данные, потому что поток не успеет завершить запись в переменную
--------------------
Get Rich or Die Tryin'
PM   Вверх
Экскалупатор
Дата 3.6.2011, 09:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

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



Dennnis, ага, и я про это говорю, приложение должно дождаться выполнения потока(кстати, не факт что того времени что ты отвел хватит, про это я уже тоже говорил). и получается что смысла во всем этом нету. точно такая же логика получиться если не использовать второй поток вообще, а все сделать в основном потоке. программа не будет выполняться дальше пока не закончит читать данные. возвращаясь к тому с чего я начал: так для чего нужно использовать второй поток? выигрыша с него нету, только проблемы с реализацией.
PM MAIL ICQ   Вверх
jonie
Дата 3.6.2011, 11:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

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



вот набрасал быстро

на форме две кнопки и textbox (первая стартует процесс, вторая cancel-ит). Больше ниче делать не надо (разве что имя файла поменять) 8-)

Для удобства работа вынесена в отдельный класс.
Код

        public Form1()
        {
            InitializeComponent();
            button2.Enabled = false;
            button1.Click += button1_Click;
            button2.Click += button2_Click;
        }

        TxtSlowReader _txtReader;

        private void button1_Click(object sender, EventArgs e)
        {
            _txtReader = new TxtSlowReader("C:\\textfile.txt");
            _txtReader.OnComplete += txtReader_OnComplete;
            _txtReader.WorkAsync();
            button1.Enabled = false;
            button2.Enabled = true;
        }

        void txtReader_OnComplete(object sender, TxtSlowReaderEventArgs e)
        {
            button1.Enabled = true;
            button2.Enabled = false;

            if (e.Error != null)
                MessageBox.Show(e.Error.ToString(), "ERROR!");
            else if(e.Lines==null)
                MessageBox.Show("Canceled!", "ok");
            else if (e.Lines != null)
                textBox1.Text = string.Join(", ", e.Lines);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (null != _txtReader)
            {
                _txtReader.Abort();
                _txtReader = null;
            }
        }
    }

    public class TxtSlowReaderEventArgs : EventArgs
    {
        public TxtSlowReaderEventArgs(Exception error, IList<string> lines)
        {
            this.Error = Error;
            this.Lines = lines;
        }

        public Exception Error { get; private set; }
        public IList<string> Lines { get; private set; }
    }

    public class TxtSlowReader
    {
        private string _filename;
        private BackgroundWorker _bw;
        public TxtSlowReader(string filename)
        {
            _filename = filename;
        }

        public void Abort()
        {
            lock (this)
            {
                if (_bw != null)
                {
                    _bw.CancelAsync();
                    _bw = null;
                }
            }
        }

        public void WorkAsync()
        {
            _bw = new BackgroundWorker();
            _bw.WorkerSupportsCancellation = true;
            _bw.DoWork += bw_DoWork;
            _bw.RunWorkerCompleted += bw_RunWorkerCompleted;
            _bw.RunWorkerAsync();
        }

        void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (null != OnComplete)
            {
                if (e.Cancelled)
                    OnComplete(this, new TxtSlowReaderEventArgs(null, null));
                else
                    OnComplete(this, new TxtSlowReaderEventArgs(e.Error, (IList<string>)e.Result));
            }
        }

        void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            List<string> rv = new List<string>();
            using (var fs = new FileStream(_filename, FileMode.Open, FileAccess.Read))
            {
                using (var txtr = new StreamReader(fs))
                {
                    string line;
                    while ((line = txtr.ReadLine()) != null)
                    {
                        lock (this)
                        {
                            if (_bw == null || _bw.CancellationPending) { rv = null; break; }
                        }

                        Thread.Sleep(200);
                        rv.Add(line);
                    }
                }
            }
            e.Result = rv;
        }

        public event EventHandler<TxtSlowReaderEventArgs> OnComplete;
    }



--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

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


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

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


 




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


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

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