0

我正在开发一个访问 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 是另一个小的用户控件。请有人告诉我解决这个问题的方法吗?

4

2 回答 2

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;
        }));
    }
}

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

于 2013-09-09T18:16:03.520 回答
2

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

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 "------";
}
于 2013-09-09T18:27:19.643 回答