Вопрос по c#, multithreading – C #, как достичь чего-то в текущем потоке, который создан в другом потоке?

3

Я пишу чат-клиент / серверное приложение на C #, и у меня возникла проблема с многопоточностью. Я написал этот простой код для отображения моей проблемы.

Я использовал thread_1 для показа формы, но он просто показывает ее секунду (возможно, thread_1 завершил работу и закрыл форму, но я сказал, что IsAlive жив!). Thread_2 пытается добраться до texBox, созданного в основном потоке, но он показывает мне:

"Cross-thread operation not valid: Control 'textBox2' accessed from a thread other than the thread it was created on."

Я не знаю, как решить первую проблему, но я решил вторую проблему с BackgroundWorker, но мне нравится делать это с потоком. Там в любом случае?

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

    Thread t1;
    Thread t2;


    private void button1_Click(object sender, EventArgs e)
    {

        t1 = new Thread(doThread1);
        t1.Name = "thread_1";

        t2 = new Thread(doThread2);
        t2.Name = "thread_2";

        t1.Start();
        t2.Start();

        MessageBox.Show(t1.IsAlive.ToString());
    }

    private void doThread1()
    {
        Form frm2 = new Form();
        frm2.Show();
    }


    private void doThread2()
    {
        try
        {
            for (int j = 10000; j > 0; j--)
                textBox.Text = j.ToString();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }


}
@Exceptive Вопрос, на который вы ссылались, удален. Ral Zarek
Форма собирается сборщиком мусора, когда doThread1 достигает ее конца. Не имеет значения, что это отдельная тема. Alxandr
Чувак, ты ошибаешься в этом. Весь пользовательский интерфейс должен оставаться в собственной ветке. Фоновые задачи могут иметь столько потоков, сколько они хотят, но фоновые задачи не могут и не должны обращаться к пользовательскому интерфейсу. linkerro
Попробуйте эту тему [Запись в TextBox из другой темы] [1] [1]:stackoverflow.com/questions/519233/… Exceptive

Ваш Ответ

2   ответа
2

вы хотите удалить поток, который вы называете потоком 1, поскольку ваш пользовательский интерфейс уже будет в потоке при запуске (все программы имеют единственный основной поток, в котором они запускаются). Тем не менее вы были на правильном пути, вы хотите поместить любые долгосрочные задачи в отдельный поток, чтобы он не блокировал пользовательский интерфейс. Единственная хитрость в том, что вы не можете напрямую манипулировать объектами пользовательского интерфейса из фоновых потоков, ими нужно манипулировать из потока, которому они принадлежат (о чем говорит сообщение об ошибке).

К счастью, есть очень простой способ сделать это в .NET. В WPF вы используете UiComponent.Dispatcher.Invoke (), а Winforms просто используют UiComponent.Invoke (). Это позволяет фоновому потоку перейти к потоку, в котором находится компонент пользовательского интерфейса, для его обновления.

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

Попробуй это

private void doThread2()
{
    try
    {
        for (int j = 10000; j > 0; j--)
        {
            textBox.Invoke(new Action(() =>
                textBox.Text = j.ToString()));
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

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

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

    private void button1_Click(object sender, EventArgs e)
    {
        Task.Factory.StartNew(() =>
        {
            for (int x = 0; x < 100000000; x++)
            {
                label1.Invoke(new Action(() =>
                    label1.Text = x.ToString()));
            }
        });
    }
}
0

Запись в TextBox из другого потока?Я думаю, что это ответ на ваш вопрос о доступе к объектам, созданным в другой теме.

Что-то пошло не так с ссылкой в первый раз.

Похожие вопросы