Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/269.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在windows窗体中实现类似web应用程序的加载程序_C#_Multithreading_Winforms_Desktop Application_Showdialog - Fatal编程技术网

C# 在windows窗体中实现类似web应用程序的加载程序

C# 在windows窗体中实现类似web应用程序的加载程序,c#,multithreading,winforms,desktop-application,showdialog,C#,Multithreading,Winforms,Desktop Application,Showdialog,当任何长时间运行的进程在windows窗体中执行时,我正在尝试显示Loader。我已经实现了这方面的代码,但加载程序正在显示,但不在centerprist位置,它将显示在屏幕的中心 代码: CPLoader是我希望在任何进程执行时显示的表单 public class CommonLoader { CPLoader cploader = new CPLoader(); readonly Form form = null; public CommonLoader(Form

当任何长时间运行的进程在
windows窗体中执行时,我正在尝试显示
Loader
。我已经实现了这方面的代码,但加载程序正在显示,但不在
centerprist
位置,它将显示在屏幕的中心

代码:

CPLoader
是我希望在任何进程执行时显示的表单

public class CommonLoader
{
    CPLoader cploader = new CPLoader();
    readonly Form form = null;

    public CommonLoader(Form frm)
    {
        form = frm;
    }

    public void ShowLoader()
    {
        try
        {
            if (form.InvokeRequired)
            {
                try
                {
                    cploader = new CPLoader();
                    cploader.ShowDialog();
                }
                catch 
                {
                    Console.WriteLine("Cp loader exception");
                }
            }
            else
            {
                Thread th = new Thread(ShowLoader);
                th.IsBackground = false;
                th.Start();
            }
        }
        catch
        {
            Console.WriteLine("Cp loader exception");
        }
    }

    /// <summary>
    /// this method will used for hide loader while process stop
    /// </summary>
    public void HideLoader()
    {
        try
        {
            if (cploader != null)
            {
                Thread.Sleep(200);
                cploader.Invoke(new Action(cploader.Close));
            }
        }
        catch
        {
            Console.WriteLine("Cp loader exception");
        }
    }
}
公共类CommonLoader
{
CPLoader CPLoader=新CPLoader();
只读形式=空;
公共公共加载程序(表格frm)
{
形式=frm;
}
公共void ShowLoader()
{
尝试
{
如果(需要调用表单)
{
尝试
{
cploader=新cploader();
cploader.ShowDialog();
}
抓住
{
Console.WriteLine(“Cp加载程序异常”);
}
}
其他的
{
Thread th=新线程(ShowLoader);
th.IsBackground=false;
th.Start();
}
}
抓住
{
Console.WriteLine(“Cp加载程序异常”);
}
}
/// 
///此方法将用于在进程停止时隐藏加载程序
/// 
公共无效HideLoader()
{
尝试
{
if(cploader!=null)
{
睡眠(200);
调用(新操作(cploader.Close));
}
}
抓住
{
Console.WriteLine(“Cp加载程序异常”);
}
}
}
我还尝试了
cploader.ShowDialog()
frm.BeginInvoke(新方法调用程序(委托(){cploader.ShowDialog(表单);}))


如果使用
BeginInvoke()
,则无法关闭加载程序。

启动屏幕、进度屏幕等在Visual Basic或Delphi桌面应用程序中出现的时间早于web应用程序。它们只是显示在应用程序顶部的无模式窗体/窗口。他们也不需要线程——当时的应用程序大多是单线程的

后台线程无论如何都无法修改UI,这意味着整个
ShowLoader
方法只会尝试调用:

cploader = new CPLoader();
cploader.ShowDialog();
所有这些都可以用

public void ShowLoader()
{
    cploader.ShowDialog();
}

public void HideLoader()
{
    cploader.Hide(); 
    //or Close if we don't intend to reuse the loader
}
指定父级

不带任何参数的调用将创建父窗口为桌面的窗口。这就是为什么窗口显示在屏幕的中心,而不是应用程序的中心

要指定所有者/父级,只需将其作为
owner
参数传递给或即可

以下代码可用于显示以当前表单为中心的对话框:

var myDialog=new MyDialogForm();
myDialog.ShowDialog(this);
这意味着
ShowLoader
可能必须接受所有者作为参数:

public void ShowLoader(Form frm)
{
    cploader.ShowDialog(frm);
}
无模式窗口

ShowDialog()
用于显示模式窗体—一种在关闭前保持焦点的窗体,就像对话框一样。这就是为什么该方法被称为
ShowDialog()
,而不是
ShowModal()

加载程序需要无模式,因此应改用
Show

public void ShowLoader(Form frm)
{
    cploader.Show(frm);
}
另一个区别是
ShowDialog
返回用户选择的结果(确定、取消等),而
Show
不返回任何结果

带有通知的模式加载程序

如果要使用
ShowDialog
创建模式加载程序,但仍要在后台执行某些工作,则需要一种从后台线程通知该加载程序的方法。您可以使用类来实现这一点

加载程序可以将
IProgress
作为属性公开。
T
参数可以是显示进度的简单字符串或整数,也可以是包含进度、字符串消息和状态指示器的复杂实体。出于懒惰的考虑,让我们使用
string
并在值为空时关闭对话框:

public IProgress<string> Progress{get;private set;}

public CPLoader()
{
    this.Progress=new Progress<string>(UpdateUI);
}

private void UpdateUI(string msg)
{
    if(String.IsNullOrWhitespace(msg))
    {       
        this.DialogResult=DialogResult.Cancel;
        this.Close(); 
    }
    else
    {
        this.SomeLabel.Text=msg;
    }
}
首先初始化加载程序,让我们可以访问
IProgress
实例。然后在后台使用
任务启动作业。运行
。当它完成时,它发送一个空的进度字符串,加载程序的
UpdateUI
方法关闭对话框作为响应


加载时需要执行工作的代码可以访问
IProgress
界面,并使用它向pro发出信号,通过“loader”(加载程序)您是指启动屏幕、进度条还是旋转球?在这方面,Web应用程序实际上模拟桌面应用程序。这样做不需要线程(事实上,线程根本无法触及UI)。只需在当前窗体的顶部显示一个无模式窗体,其中包含您想要显示的内容。这意味着,只需使用
Show
而不是
ShowDialog()
,并在需要隐藏时调用
Hide()
。所有其余的代码在最坏的情况下都会死锁,或者在最好的情况下再次在UI线程中运行-
BeginInvoke()
意味着
在UI线程上运行此方法
至于居中,您没有发布任何试图在特定位置显示表单的代码,或者表单的属性。唯一相关的代码是
cploader=newcploader();cploader.ShowDialog()显示模式窗体而不指定父级。这将创建一个其父级为桌面的对话框。您应该将父窗体作为参数传递给
ShowDialog
Show
@panagiotis kanavos,我已经更新了问题,请查看它。我认为它会阻止进程,直到用户关闭它。我需要在进程执行时显示对话框,完成后自动关闭,无需用户交互。@HirenPatel为什么?你试过了吗?即使
ShowDialog()
不会阻塞线程,它也会将焦点保留在表单上<另一方面,显示代码>显示
时不会阻止用户使用同一应用程序中的其他控件或窗体
void Work(IProgress<string> progress)
{
    for(int i=0;i<1000000;i++)
    {
        //Do something CPU intensive
        //Report every 1000 items
        if(i%1000==0)
        {
            progress.Report($"{i} out of 1000000");
        }
    }
    //This tells the loader to close.
    progress.Report("");
}
var loader=new CPLoader();
var task=Task.Run(()=>DoWork(loader.Progress));
loader.ShowDialog();
await task;