2010-11-16 3 views
3
Monitor moni = new Monitor(); 
Thread t = new Thread(() => moni.CurrUsage(nics,200)); 
t.Start(); 

Я запускаю поток с именем 't' внутри функции Form1_Load. Я добавил кнопку. При нажатии на эту кнопку поток 't' должен прекратить выполнение и создать новый поток с этими параметрами.Как прервать поток, запущенный внутри другой функции?

Monitor moni = new Monitor(); 
Thread t = new Thread(() => moni.CurrUsage(nics,950)); 
t.Start(); 

Я знаю, что в случае Form_Load я могу использовать

t.Abort(); 

ответ

5

Делая t членом формы, вы можете ссылаться на нее позже в обработчике событий нажатия кнопки.

Изящный отторж. Несмотря на то, что t.Abort() выполняет свою работу, вы можете оставить полузаработанные данные в потоке t. Вы можете поймать ThreadAbortException в потоке t, чтобы изящно завершить обработку.

Опасайтесь перекрытия. Вторая проблема заключается в том, что ваш поток, возможно, не был прерван, пока ваш новый поток уже запущен. Вы можете предотвратить это, позвонив по телефону t.Join() после звонка t.Abort().

Надеюсь, это поможет.

2

Сделать Thread t частный член вашей формы.

public partial class MainForm : Form 
{ 
    private Thread t; 
} 
1

Один из способов сделать Thread t глобальной переменной (место за пределами Form_Load). Затем он может быть доступен и изменен из любого метода в этом классе.

Чтобы создать экземпляр темы, используйте t = new Thread(.....

Перед тем, как прервать нить, убедитесь, что она не является нулевой.

1

Вам необходимо сделать объект Thread доступным в обоих местах, к которым вам нужно получить доступ. В этом случае работа с частным varaible будет работать.

например.

public class MyClass 
{ 
    private Thread MyThread 
    { 
    get; 
    set; 
    } 


    private void myfunc1() 
    { 
    MyThread = new Thread(() => moni.CurrUsage(nics,200)); 
    MyThread.Start(); 
    } 

    private void myfunc2() 
    { 
    MyThread.Abort(); 

    // I really need to wait until this thread has stopped... 
    MyThread.Join(); 
    } 

} 
+0

хорошее описание. я очень помог мне – vishnu

0

Добавление к уже приведенным ответам:

Обратите внимание, что .Join() будет блокировать вашу текущую (UI) нить, оставив ваше приложение не реагирует на пользователь.

Как и другое: избегайте использования .Abort() с помощью флага в вашем классе Monitor для выхода из задачи, которую вы выполняете, если это возможно. Затем вы можете дождаться .Join(), но у вас есть полный контроль над состоянием в фоновом потоке.

public class Monitor 
{ 
    private bool _cancel = false; 

    public void Cancel() 
    { 
     _cancel = true; 
    } 

    public void CurrUsage(Nics nics, int n) 
    { 
     _cancel = false; 
     // ... 
     while (!_cancel) 
     { 
     // do some stuff 
     } 
    } 
} 

в вашей форме

private Monitor _monitor { get; set; } 
private Thread _t; 
public void Button_Click(...) 
{ 
    _monitor.Cancel() 
    _t.Join()  // will return as your background thread has finished cleanly 
    _t = new Thread(() => _monitor.CurrUsage(nics,950)); 
    t.Start(); 
} 
0

Как уже отмечалось, все, что вам нужно для того, чтобы вызвать Abort является ссылкой на поток (так же, как и любой другой объект в .NET).

Однако

Вы должны серьезно рассмотреть вопрос о переосмыслении этого подхода. В общем, вызов Abort обескуражен, так как он не дает целевой теме достаточную возможность достичь точки остановки. Хотя это иногда необходимо (или единственный вариант), это почти всегда лучшая идея спросить целевую нить, чтобы остановить (как правило, через volatile bool, а не заставляя его, как это.

Например,

public class ThreadClass 
{ 
    private volatile bool stopRequested; 
    private Thread thread; 

    public void Start() 
    { 
     stopRequested = false; 
     thread = new Thread(ThreadMethod); 

     thread.Start(); 
    } 

    public void Stop() 
    { 
     stopRequested = true; 

     if(!thread.Join(5000)) thread.Abort(); // forcefully abort if not 
               // completed within 5 seconds 
    } 

    private void ThreadMethod() 
    { 

    } 
} 

Ваш код затем переходит в ThreadMethod. Внутри метода периодически проверяйте значение stopRequested.Если оно верно, выполните любую очистку (если есть) и изящно вернитесь из потока. Если содержимое представляет собой цикл, общий практика заключается в том, чтобы поместить проверку в начале цикла (при условии, что петля достаточно плотная) и выйдите раньше, если значение равно true. Точное размещение действительно зависит от кода, но общая идея заключается в том, что его следует проверять достаточно часто, чтобы поток был довольно быстро после его установки, независимо от того, когда это произойдет.

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