我的表单时,它是从另一个线程启动不能正常显示 [英] My form doesn't properly display when it is launched from another thread

查看:139
本文介绍了我的表单时,它是从另一个线程启动不能正常显示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的情况:
我正在开发具有以下结构的简单应用:




  • FormMain(启动点)

  • FormNotification

  • CompleFunctions



右键<? / p>

那么,在 FormMain 我有以下功能:

 私人无效DoItInNewThread(ParameterizedThreadStart pParameterizedThreadStart,对象pParameters,ThreadPriority pThreadPriority)
{
螺纹oThread =新主题(pParameterizedThreadStart);
oThread.CurrentUICulture = Settings.Instance.Language;
oThread.IsBackground = TRUE;
oThread.Priority = pThreadPriority;
oThread.Name =μRemote:后台操作;
oThread.Start(pParameters);
}



所以,每次我需要调用位于 ComplexFunctions 我做到以下几点:

  //这是FormMain.cs 
串strSomeParameter =拉拉
DoItInNewThread(新ParameterizedThreadStart(ComplexFunctions.DoSomething),strSomeParameter,ThreadPriority.Normal);



其他类,FormNotification,它可显示给用户的过程中的一些信息的表格。
这FormNotification可以从FormMain或ComplexFunctions被调用。
示例:

  //这是ComplexFunctions.cs 
公共无效DoSomething的(字符串pSomeParameter)
{
//试想一些耗时的任务
FormNotification formNotif =新FormNotification();
formNotif.Notify();
}



FormNotify有一个计时器,所以10秒关闭表单后。我没有使用formNotif.ShowDialog,因为我不想给注重这种形式。
你可以检查此链接看什么。我做的通知



好吧,这里有一个问题:
当我打电话的 FormNotify ComplexFunction 这是从另一个线程在一个名为 FormMain ...这个 FormNotify 消失后的几毫秒。
这是相同的效果,当你做这样的事情:

 使用(FormSomething formSomething =新FormSomething)
{
formSomething.Show();
}

如何避免这种情况?



这是我不希望使用可能的解决方案:




  • 使用了Thread.Sleep (10000)在FormNotify

  • 使用FormNotif.ShowDialog()



这是一个简单的场景(FormNotify做一些其他花哨的东西,仅仅停留10秒,但他们是无关的,看问题)。



感谢您的时间!
和请,对不起,我的英语水平。


解决方案

几乎每个GUI库设计为仅允许改变GUI电话在指定用作一个单独的线程来进行(称为UI线程)。如果你是在另一个线程,您需要安排调用更改UI线程要做出的GUI。在.NET中,做到这一点的方法是调用调用(同步)或的BeginInvoke(异步)。等效的Java Swing调用的invokeLater() - 有几乎在每一个GUI库类似的功能。



有一种叫做线程关联。有两个线程在一个WinForm应用,一个用于呈现和一种用于管理用户界面。你只用用户界面线程处理。渲染线程处于隐藏状态 - 在后台运行。在UI线程创建可以操纵UI的唯一对象 - 即对象与UI线程线程关联



既然,你要更新的用户界面(显示的通知)从不同的线程比UI线程。因此,在您的工作线程定义了一个代理,并FormMain监听此事件。在事件处理程序(在FormMain定义)编写代码来显示FormNotify。



当你想显示通知火从工作线程的事件。



在比控制创建线程的其他线程试图访问的该控件的方法或属性之一,它通常会导致不可预知的结果。一个常见的​​无效的线程活动是错误的线程访问控件的Handle属性的呼叫。设置CheckForIllegalCrossThreadCalls真找,更容易诊断此线程活动,同时调试。需要注意的是非法的跨线程调用将始终引发异常时,应用程序启动调试器外



请注意:设置CheckForIllegalCrossThreadCalls到TURE只能在DEBUGGIN情况下,只能进行。无法预测的结果会发生,你会风试图追逐,你将有一个difficuly大部头发现的bug。


Here's the situation: I'm developing a simple application with the following structure:

  • FormMain (startup point)
  • FormNotification
  • CompleFunctions

Right?

Well, in FormMain I have the following function:

private void DoItInNewThread(ParameterizedThreadStart pParameterizedThreadStart, object pParameters, ThreadPriority pThreadPriority)
{
    Thread oThread = new Thread(pParameterizedThreadStart);
    oThread.CurrentUICulture = Settings.Instance.Language;
    oThread.IsBackground = true;
    oThread.Priority = pThreadPriority;
    oThread.Name = "μRemote: Background operation";
    oThread.Start(pParameters);
}

So, everytime that I need to call a time consuming method located on ComplexFunctions I do the following:

// This is FormMain.cs
string strSomeParameter = "lala";
DoItInNewThread(new ParameterizedThreadStart(ComplexFunctions.DoSomething), strSomeParameter, ThreadPriority.Normal);

The other class, FormNotification, its a Form that display some information of the process to the user. This FormNotification could be called from FormMain or ComplexFunctions. Example:

// This is ComplexFunctions.cs
public void DoSomething(string pSomeParameter)
{
    // Imagine some time consuming task
    FormNotification formNotif = new FormNotification();
    formNotif.Notify();
}

FormNotify has a timer, so, after 10 seconds closes the form. I'm not using formNotif.ShowDialog because I don't want to give focus to this Form. You could check this link to see what I'm doing in Notify.

Ok, here's the problem: When I call FormNotify from ComplexFunction which is called from another Thread in FormMain ... this FormNotify disappears after a few milliseconds. It's the same effect that when you do something like this:

using(FormSomething formSomething = new FormSomething)
{
   formSomething.Show();
}

How can avoid this?

These are possible solutions that I don't want to use:

  • Using Thread.Sleep(10000) in FormNotify
  • Using FormNotif.ShowDialog()

This is a simplified scenario (FormNotify does some other fancy stuff that just stay for 10 seconds, but they are irrelevant to see the problem).

Thanks for your time!!! And please, sorry my english.

解决方案

Almost every GUI library is designed to only allow calls that change the GUI to be made in a single thread designated for that purpose (called the UI thread). If you are in another thread, you are required to arrange for the call to change the GUI to be made in the UI thread. In .NET, the way to do that is to call Invoke (synchronous) or BeginInvoke (asynchronous). The equivalent Java Swing call is invokeLater() -- there are similar functions in almost every GUI library.

There is something called thread affinity. There are two threads in a WinForm Application, one for rendering and one for managing user interface. You deal only with user interface thread. The rendering thread remains hidden - runs in the background. The only objects created on UI thread can manipulate the UI - i.e the objects have thread affinity with the UI thread.

Since, you are trying to update UI (show a notification) from a different thread than the UI thread. So in your worker thread define a delegate and make FormMain listen to this event. In the event handler (define in FormMain) write code to show the FormNotify.

Fire the event from the worker thread when you want to show the notification.

When a thread other than the creating thread of a control tries to access one of that control's methods or properties, it often leads to unpredictable results. A common invalid thread activity is a call on the wrong thread that accesses the control's Handle property. Set CheckForIllegalCrossThreadCalls to true to find and diagnose this thread activity more easily while debugging. Note that illegal cross-thread calls will always raise an exception when an application is started outside the debugger.

Note: setting CheckForIllegalCrossThreadCalls to ture should only be done in DEBUGGIN SITUATIONS ONLY. Unpredicatable results will occur and you will wind up trying to chase bugs that you will have a difficuly tome finding.

这篇关于我的表单时,它是从另一个线程启动不能正常显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆