Мой код многопоточный форма правильная?


Основная идея заключается в следующем:

Есть две кнопки: dowork в кнопку и отменить кнопку.

В dowork в кнопку нужно запустить поток, чтобы сделать некоторые работы, если этот поток был уже запущен и не отменено.

На отмены кнопка отмены рабочий поток, если он запущен.

Пожалуйста, игнорировать тот факт, что он называет потоком.Прервать() на данный момент, это отдельная тема, о которой я скажу позже.

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

Вот код:

    private Thread m_WorkingThread;
    private bool m_finishedWorking;

    public Form()
    {
        InitializeComponent(); // initialize all the form controls.
        m_WorkingThread = null;
        m_finishedWorking = false;
    }

    private void bDoWork_Click(object sender, EventArgs e)
    {            
        if (m_WorkingThread != null)
            if(m_WorkingThread.IsAlive  || m_finishedWorking)
                return;

        ThreadStart ts = new ThreadStart(DoWork);
        Thread t = new Thread(ts);
        t.Start();
        m_WorkingThread = t;

    }
    private void bCancel_Click(object sender, EventArgs e)
    {
        AbortThread(m_WorkingThread);
        m_finishedWorking = false;
    }
    private void AbortThread(Thread t)
    {
        if (t != null)
            if (t.IsAlive)
                t.Abort();
    }
    private void DoWork()
    {
        // do some work here, maybe using Invokes / BeginInvokes to update any controls.

        m_finishedWorking = true;
    }


815
1
задан 5 июня 2011 в 03:06 Источник Поделиться
Комментарии
3 ответа

Вы рассматривали с помощью BackgroundWorker? Это может спасти вас от неприятностей.

Однако, он использует пул потоков и вам лучше создать ваши собственные темы, если у вас есть любой из следующих требований:


  • Требуется резьба на переднем плане.

  • Вам нужна нить, чтобы иметь определенный приоритет.

  • У вас есть задачи, которые вызывают поток блокировать в течение длительных периодов времени. Пул потоков имеет максимальное количество потоков, поэтому большое количество заблокированных потоков может предотвратить задачи с началом.

  • Вам нужно поместить поток в однопотоковый апартамент. Все потоки ThreadPool в многопоточном апартаменте.

  • Вы должны иметь стабильный идентификатор, связанный с потоком, или посвятить какое-нить задание.

Я добавить мой комментарий к ответу "Питер К." Здесь, как казалось, чтобы удовлетворить вас.


Мьютекс-это немного перебор, как это работает
на несколько процессов. Надо
использовать замки (т. е. монитор), когда есть
не нужно синхронизировать через
процессов. В любом случае, я не вижу здесь
какой-либо необходимости для блокировок при условии, что
в bDoWork_Click() всегда вызывается
из потока пользовательского интерфейса. Он создает только
новый поток, если существующий поток
не в живых. Однако, ресурсы, используемые
с помощью метода dowork() должны быть защищены с
замки, если они являются общими с другими
потоков.

5
ответ дан 7 июня 2011 в 11:06 Источник Поделиться

Пытаясь использовать общие переменные-это вообще плохо(ТМ). Обычный способ сделать кросс-нить замок / проверка ресурса через мьютекс.

Что-то вроде этого, хотя я еще не составлена или проверена его:

private Thread m_WorkingThread;
private static Mutex m_FinishedWorking = new Mutex();

public Form()
{
InitializeComponent(); // initialize all the form controls.
m_WorkingThread = null;
}

private void bDoWork_Click(object sender, EventArgs e)
{
if (m_WorkingThread != null)
if(m_WorkingThread.IsAlive)
return;

ThreadStart ts = new ThreadStart(DoWork);
Thread t = new Thread(ts);
t.Start();
m_WorkingThread = t;

}
private void bCancel_Click(object sender, EventArgs e)
{
AbortThread(m_WorkingThread);
}
private void AbortThread(Thread t)
{
if (t != null)
if (t.IsAlive)
t.Abort();
}
private void DoWork()
{
m_FinishedWorking.WaitOne();
// do some work here, maybe using Invokes / BeginInvokes to update any controls.

// Must be called if the thread is aborted.
m_FinishedWorking.ReleaseMutex();
}

1
ответ дан 5 июня 2011 в 03:06 Источник Поделиться

Я не мог найти что-то неправильно в коде.

Но я бы предложил, конечно, в зависимости от вашей версии платформы, чтобы использовать задачи вместо потоков - системы.Резьбонарезной.Задач предлагает вам очень хороший API.

Вот небольшой пример, возможно, не пуленепробиваемый - но я думаю, вы получите идею:

private Task task;
private CancellationTokenSource tokensource;
private CancellationToken token;

public Form1() {
InitializeComponent();
tokensource = new CancellationTokenSource();
token = tokensource.Token;
this.Cancel.Enabled = false;
}

private void DoWork_Click(object sender, EventArgs e) {
if (task != null && !task.IsCompleted) return;

this.DoWork.Enabled = false;
this.Cancel.Enabled = true;
task = Task.Factory.StartNew(() => DoWorkAction(), token)
.ContinueWith(_ => { this.DoWork.Enabled = true; this.Cancel.Enabled = false; },
TaskScheduler.FromCurrentSynchronizationContext());
}

private void Cancel_Click(object sender, EventArgs e) {
tokensource.Cancel();
}

private void DoWorkAction() {
Thread.Sleep(5000);
}

1
ответ дан 8 июня 2011 в 05:06 Источник Поделиться