2013-11-22 5 views
0

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

Во-первых, коды,

public frmCEX() 
    { 
     InitializeComponent(); 
     refreshTicker(); 
    } 

    private void btnRefresh_Click(object sender, EventArgs e) 
    { 
     refreshTicker(); 
    } 

    private void refreshTicker() 
    { 
     ssStatus.Text = "Updating ticker.."; 
     btnRefresh.Text = "Updating"; 
     btnRefresh.Enabled = false; 
     ssUpdated.Text = "Last updated: -"; 

     APIManager apim = new APIManager(); 
     Ticker tk = apim.getTicker(); 

     //blablabla, do some work 

     ssUpdated.Text = "Last updated: " + DateTime.Now.ToString(); 
     ssStatus.Text = ""; 
     btnRefresh.Text = "Refresh"; 
     btnRefresh.Enabled = true; 
    } 

    private void cbxRefresh_CheckedChanged(object sender, EventArgs e) 
    { 
     if (cbxRefresh.Checked) 
     { 
      Thread thread1 = new Thread(() => BGRefreshThread(Convert.ToInt32(nupRefreshSecs.Value))); 
      thread1.Start(); 
     } 
     else 
     { 
      // IF REFRESH CHECKBOX IS UNCHECKED, STOP THE THREAD THAT IS REFRESHING 
     } 
    } 

    private void BGRefreshThread(int delay) 
    { 
     refreshTicker(); 
     System.Threading.Thread.Sleep(delay * 1000); 
    } 

Моя главная проблема заключается в методе cbxRefresh_CheckedChanged, в основном, как это работает, является то, что, когда пользователь флажок «Автоматическое обновление» флажок в главном интерфейсе, то CheckedChanged метод создаст новый поток BGRefreshThread, который запустится в фоновом режиме и обновит тикер, а после того, как флажок снят снова, он завершит поток, который обновит тикер.

Однако у меня возникла проблема с окончанием потока после его запуска, поскольку после завершения метода checkedchanged поток больше не существует в контексте, когда флажок снят в следующий раз.

Может ли кто-нибудь посоветовать, как я могу заставить это работать? Действительно новое для многопоточного программирования.

** EDIT: Я нашел решение этой проблемы, но прямо сейчас, когда вновь созданный поток пытается вызвать «refreshTicker», который обновляет метки и кнопки на основном пользовательском интерфейсе (который находится в основном потоке) , это дает мне эту ошибку:

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

любые советы по этому вопросу **

+0

Сохраните thread1 в более широком диапазоне? M Используйте сигнализацию, используйте эту библиотеку задач. –

+0

Вы не можете получить доступ к элементу управления UI из другого потока, кроме потока пользовательского интерфейса, вам нужно использовать 'Control.Invoke' или Dispatcher. См. [Здесь] (http://stackoverflow.com/questions/5037470/cross-thread-operation-not-valid) для получения дополнительной информации –

+0

спасибо! Я изменил «refreshTicker()»; на "this.Invoke ((MethodInvoker) delegate() {refreshTicker();});" но тикер по-прежнему не обновляется, кажется, что поток по какой-то причине не работает. – InnovativeDan

ответ

0

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

private Thread thread1; 

private void cbxRefresh_CheckedChanged(object sender, EventArgs e) 
    { 
     if (cbxRefresh.Checked) 
     { 
      thread1 = new Thread(() => BGRefreshThread(Convert.ToInt32(nupRefreshSecs.Value))); 
      thread1.Start(); 
     } 
     else 
     { 
      thread1.Abort(); 
     } 
    } 

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

+0

какие чеки вы предлагаете? и что является подходящим способом для завершения потока? – InnovativeDan

+3

Do * not ever * use 'Thread.Abort()'! (http://stackoverflow.com/questions/710070/timeout-pattern-how-bad-is-thread-abort-really) –

+0

Теперь у меня есть большая проблема, я обновил вопрос выше с помощью редактирования, может кто угодно помогите мне с этим? – InnovativeDan

1

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

Что я могу сделать, чтобы остановить темы грациозно это: Перед тем, как создать и запустить поток создать ManualResetEvent, который я использую, чтобы сигнализировать нить бросить:

private ManualResetEvent m_stopThread = new ManualResetEvent(false); 

Чтобы остановить нить я установить событие где-то в моем коде и ждать поток до конца:

m_stopThread.Set(); 
m_myThread.Join(); 

код нить нуждается для учета остановки:

while (true) 
{ 
    // Stop the thread if the handle is set after 1 ms 
    if (m_stopThread.WaitOne(1, false)) 
     break; 

    // Do some work 
} 
+0

Теперь у меня есть большая проблема, я обновил вопрос выше с помощью редактирования, может ли кто-нибудь помочь мне с ним? – InnovativeDan

+0

Вы не можете получить доступ к компонентам в потоке пользовательского интерфейса из любого другого потока. На это ответили здесь миллион раз. Используйте 'this.Invoke' (Windows Forms) или' this.Dispatcher.Invoke' (WPF), чтобы вернуться к потоку пользовательского интерфейса. –

Смежные вопросы