Быстрый вопрос: возможно ли показать диалог / Показать форму из нового потока, который был запущен из события Load другой формы?
РЕДАКТИРОВАТЬ: Почему невозможно показатьDialog / Показать форму из нового потока, который был запущен из события Load другой формы?
Предполагаемое требование - показать загрузочную форму / спираль с загрузкой текста и, возможно, больше / во время загрузки дочерней формы MDI, что приведет к зависанию всего приложения.
Требование гласит, что «Форма загрузчика» не должна висеть. Таким образом, требуется новая тема.
Сводка кода, которую я реализовал до сих пор:
MDI Parent:
delegate void ManipulateJob();
public void StartJob()
{
Cursor.Current = Cursors.WaitCursor;
if (this.InvokeRequired)
//case when the Loader is started from a different thread than the main we need to invoke
{
System.Diagnostics.Debug.WriteLine("-> MainForm.StartJob InvokeRequired");
ManipulateJob callback = new ManipulateJob(StartJob);
this.Invoke(callback, new object[] { });
}
else
{
tasks_running++;
System.Diagnostics.Debug.WriteLine("-> MainForm.StartJob InvokeNotRequired");
if ((this.t == null || !this.t.IsAlive)&&tasks_running == 1)
{
System.Threading.ThreadStart ts = new System.Threading.ThreadStart(StartDifferent);
this.t = new System.Threading.Thread(ts);
this.t.Name = "UI Thread";
System.Diagnostics.Debug.WriteLine(" **starting thread");
this.t.Start();
while (_form==null||!_form.IsHandleCreated)
//do not continue until the loader form has been shown when this is enabled
//the whole program hangs here when StartJob is called within Load event
{
System.Threading.Thread.Yield();
}
}
}
System.Diagnostics.Debug.WriteLine("<- MainForm.StartJob");
}
private static frmLoading _form;
public void StartDifferent()
{
System.Diagnostics.Debug.WriteLine(" **thread started");
_form = new frmLoading();
System.Diagnostics.Debug.WriteLine(" **loader created");
_form.Icon = this.Icon;
System.Diagnostics.Debug.WriteLine(" **loader icon set");
_form.ShowDialog();
System.Diagnostics.Debug.WriteLine(" **thread terminating");
}
public void StopJob()
{
if (this.InvokeRequired) //in case this is called from a different thread
{
System.Diagnostics.Debug.WriteLine("-> MainForm.StopJob InvokeRequired");
ManipulateJob callback = new ManipulateJob(StopJob);
this.Invoke(callback, new object[] { });
}
else
{
System.Diagnostics.Debug.WriteLine("-> MainForm.StopJob InvokeNotRequired");
if (tasks_running>0&&--tasks_running == 0)
{
StopDifferent();
}
}
System.Diagnostics.Debug.WriteLine("<- MainForm.StopJob");
Cursor.Current = Cursors.Default;
}
delegate void CloseLoadingForm();
public void StopDifferent()
{
System.Diagnostics.Debug.WriteLine("-> MainForm.StopDifferent");
try
{
if (_form != null && _form.IsHandleCreated)
{
CloseLoadingForm callback = new CloseLoadingForm(_form.Close);
//_form itself is always on a different thread thus, invoke will always be required
_form.Invoke(callback);
}
}
finally
{
try
{
if (this.t != null && this.t.ThreadState == System.Threading.ThreadState.Running)
this.t.Join();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(" MainForm.StopDifferent t.Join() Exception: " + ex.Message);
}
}
System.Diagnostics.Debug.WriteLine("<- MainForm.StopDifferent");
}
пример дочерней формы:
private void frmPricingEvaluationConfig_Load(object sender, EventArgs e)
{
//taking out the following and putting it before
//Form frm = new Form();
//frm.Show(); works
if (this.MdiParent is IThreadedParent)
{
((IThreadedParent)this.MdiParent).StopJob();
}
// the loader form is not displayed yet
System.Diagnostics.Debug.WriteLine(" loading pricingEvaluationConfig");
loadPricingClasses();
loadEvaluationClasses();
if (this.MdiParent is IThreadedParent)
{
((IThreadedParent)this.MdiParent).StopJob();
}
}
//loader form displays here, but is unable to close because the closing has been called
пожалуйста, не обращайте внимания на названия и тот факт, что есть 2 подходящих набора начала и конца.
Вопрос заключается в том, что всякий раз, когда я вызываю Startjob из form1_Load (отправитель объекта, EventArgs e), _form (загрузчик AKA) не отображается, пока не завершится метод Load.
EDIT:
Другими словами, загрузчик не отображается до тех пор, пока не отобразится фактическая форма, единственный раз, когда загрузчик «показан» (отображается на экране), это когда фактическая форма завершена, метод onLoad.
: EndEdit
если я вычитаю Startjob из метода обработчика загрузки и помещаю его перед объявлением и Show (), тогда все работает так, как и предполагалось
EDIT:
Я предполагаю, без каких-либо доказательств, что метод CreateHandle () формы, который вызывается в методах ShowDialog () и Show (), получает доступ к статическому свойству где-нибудь, проверяя, были ли уже созданы какие-либо дескрипторы, и если это так, он складывает свое собственное создание после текущего Создание дескриптора, потому что во время всего этого кода где-то код пытался закрыть () загрузчик / всплеск и выдал ошибку, говорящую «Не удается закрыть () форму, создающую дескриптор». Поэтому я предположил, что метод CreateHandle () имеет нечто похожее на мой
while() { Thread.Yield(); }
Таким образом создаются 2 потока / 1 из которых является потоком создателя Loader \ Splash /, которые непрерывно уступают друг другу.
В принципе, я не понимаю, почему все это происходит, если мои предположения верны, почему формы должны стоять в очереди друг за другом?
: EndEdit
Я с радостью отвечу на все вопросы и замечания по поводу кода, пожалуйста, спросите, если что-то, что я здесь делаю, расплывчато, или вы не совсем понимаете необходимость этого.