表格在第二次打开时冻结

时间:2013-09-09 17:47:46

标签: c# .net multithreading winforms wcf

我正在开发一个访问WCF服务的Windows窗体应用程序。我遇到了一个很大的问题,我无法预测它的原因。甚至Visual Studio调试器也没有在“输出”视图中显示任何异常。场景是这样的,我有一个自定义用户控件,上面有linkLabel。只要单击链接标签,就会打开一个表单并将类对象传递给它。此对象的类定义驻留在远程服务器上的WCF服务上。现在的问题是,当我单击linkLabel时,表单会根据传递给它的类对象完美地加载每个组件。但是,当我关闭此表单并再次单击linkLabel时,表单将打开,但在加载某些元素后会立即冻结。我尝试了很多代码变体。编辑了我认为会影响的许多代码。但他们都没有表现出差异。因为,我不知道代码究竟在哪里出错,我发布了linkLabel点击代码和点击后调用的函数。

private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
      Enabled = false;
      string temp = Title.Text;
      Title.Text = "Opening...";
      System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(openTopic));
      t.Start();

      Title.Text = temp;
      Enabled = true;
}

void createTopicWindow()
{
      TopicViewer t = new TopicViewer(t);
      Invoke(new Action(() => t.Show()));
}
private void openTopic()
{
      Invoke(new Action(() => createTopicWindow()));
}

以上是经过编辑的代码,因为我之前收到了Cross thread exception

以下是单击linkLabel时调用的表单构造函数的代码:

 try
 {
        InitializeComponent();
        this.t = topic;
        if (IsHandleCreated == false)
            CreateHandle();
        System.Threading.Thread th = new System.Threading.Thread(new System.Threading.ThreadStart(loadTopic));
        th.Start();
        Common.openedTopics.Add(this);
        AddComment addComment1 = new AddComment();
        addComment1.Topic = t;
        addComment1.Dock = DockStyle.Fill;
        panel5.Controls.Add(addComment1);
        backgroundWorker1.RunWorkerAsync();
  }
  catch (Exception)
  { }

void loadTopic()
{

     Invoke(new Action(()=>tHead = new TopicHeader()));
     Global.SetControlPropertyThreadSafe(tHead,"Topic", t);
     Global.SetControlPropertyThreadSafe(tHead,"Dock", DockStyle.Fill);
     Invoke(new Action(()=>panel1.Controls.Add(tHead)));
     Global.SetControlPropertyThreadSafe(this,"Text", t.Title + " - Topic Viewer");
     if (t.Description.Trim().Length > 0)
     {
         Global.SetControlPropertyThreadSafe(webBrowser1, "DocumentText", t.Description);
     }
     else
     {
         Invoke(new Action(() => tabControl1.TabPages[0].Dispose()));
     }

     Global.SetControlPropertyThreadSafe(tabPage2, "Text", "Comments (" + client.getComCount(t.TopicID) + ") ");

 }

TopicHeader是另一个小用户控件。 请有人告诉我解决方案吗?

2 个答案:

答案 0 :(得分:2)

我不能直接回答你的问题,但这可能会暂缓。

public void Form_Load()
{
    // do some stuff on the gui-thread



    // i need to do something that takes a long time:
    ThreadPool.QueueUserWorkItem((state) =>
    {
        // i'll execute it on the ThreadPool
        // Long running code....




        // update results in mainform on gui thread.
        Invoke(new Action( delegate
        {
            // because the invoke will execute this on the gui-thread, you'll able to update controls.

            // update my gui controls.             
            DataGrid.Source = myReceiveDataThing;
        }));
    }
}

您可以展开代码,以检查表单是否仍然有效。

答案 1 :(得分:2)

如果您使用的是.Net 4.5,那么使用async/await将是最简单的解决方案。这样,您就不需要任何Invoke s

async private void Form1_Load(object sender, EventArgs e)
{
    string s = await Task<string>.Factory.StartNew(LongRunningTask, 
                                                 TaskCreationOptions.LongRunning);
    this.Text = s;
}

string LongRunningTask()
{
    Thread.Sleep(10000);
    return "------";
}