使用Abort()停止多线程时冻结GUI?

时间:2012-08-17 08:58:35

标签: c# multithreading

我有一些代码如下:

表单

    List<WebRequestUri> lwebrequest = new List<WebRequestUri>();

    public Form1()
    {
        InitializeComponent();
    }

    private void Start_Click(object sender, EventArgs e)
    {
        Thread thread = new Thread(new ParameterizedThreadStart((object context) =>
            {
                DoWork();
            }));
        thread.IsBackground = true;
        thread.Start();            
    }

    void DoWork()
    {
        lwebrequest = new List<WebRequestUri>();
        for (int i = 0; i < 100; i++)
        {
            WebRequestUri wp = new WebRequestUri();
            wp.Start();
            lwebrequest.Add(wp);
        }
    }

    private void Stop_Click(object sender, EventArgs e)
    {                  
        for (int i = 0; i < lwebrequest.Count; i++)
        {               
            lwebrequest[i].Abort();
        }
    }

工人阶级:

class WebRequestUri
{
    Thread thread = null;
    WebRequest webRequest = null;
    WebResponse webResponse = null;
    StreamReader sr = null;

    public void Start()
    {
        thread = new Thread(new ParameterizedThreadStart((object context) =>
            {
                SendRequest();
            }));
        thread.IsBackground = true;
        thread.Start();
    }

    public void Abort()
    {            
        if (webResponse != null) webResponse.Close();
        if (webRequest != null) webRequest.Abort();
        if (thread != null) thread.Abort();            
    }

    public void SendRequest()
    {
        webRequest = WebRequest.Create("http://google.com");

        webRequest.ContentType = "application/x-www-form-urlencoded";
        webRequest.Method = "GET";         
       try
        {
            webRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback), webRequest);
        }
        catch (WebException)
        {
        }
    }

    private void GetResponseCallback(IAsyncResult asynchronousResult)
    {
        try
        {
            webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
            webResponse = (HttpWebResponse)webRequest.EndGetResponse(asynchronousResult);
            sr = new StreamReader(webResponse.GetResponseStream());
            string response = sr.ReadToEnd();
            Console.Write(response);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
}

当我尝试点击停止按钮时,我遇到了问题。我看到我的表格被封锁了。我不确定我的停止功能是对还是错。你能给我一些建议吗?感谢

2 个答案:

答案 0 :(得分:0)

看起来您正在尝试同步中止可能已经启动的Web请求。这些请求的处理可能正在进行中,因此我怀疑此时可能会暂停中止呼叫。如果您只是想要中止,我会考虑在另一个工作线程上执行此操作,以便GUI至少可以返回。

答案 1 :(得分:0)

其他人建议可能导致挂起。 然而,更重要的是Thread.Abort的实际用法。

它被视为a very bad thing to do,您不会相信它可能导致的问题数量和细微错误。

好消息是你通常不需要它,不合时宜地完成异步任务可以并且应该由应用程序本身处理。考虑一下您的用例,例如:

你打算通过中止来完成什么?你试图中止请求吗?你不能,因为它已经在进行中。它将到达目的地并被处理,无论另一方是否有人在等待它。 但是,如果您试图避免不必要的计算 - 您可以完全控制。您可以在名为“abortRequested”的类中保留布尔成员,而Abort方法只将其设置为“true”。您想要中止的方法需要不时检查该成员,以决定是否应该继续执行。

如果您愿意,我们可以进一步分析您的用例。

修改: 它看起来像这样:

bool stopped = false; // can make this thread safe if you want.

// Assuming you have a computation in a loop.
compouteAsynch(){

   for(var workItme in workItems){
     if(!stopped){
      dostuff(workItem)
     }
   }
}

void stop(){
   stopped = true; // work will not stop immediately. Only in the next iteration.
}

您可以根据需要控制“已停止”采样的粒度。但是,您必须意识到无法在任何地方对其进行采样。例如,当线程正在对DB执行查询时,您无法检查它。这应该足够好了。