Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/240.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
.net 可以调用并执行引发异常的主UI线程代码吗?_.net_Exception_Process_Delegates_Invoke - Fatal编程技术网

.net 可以调用并执行引发异常的主UI线程代码吗?

.net 可以调用并执行引发异常的主UI线程代码吗?,.net,exception,process,delegates,invoke,.net,Exception,Process,Delegates,Invoke,在下面的代码中,我使用进程对象来执行一系列DOS批处理文件。 举个例子,我正在缩短脚本列表 后续(1+)脚本通过事件处理程序(而不是for循环)执行。这样,每个后续脚本仅在前一个脚本完成时运行。现在,由于某种原因,在执行第二个脚本时,我无法获取捕获到的异常以在状态栏中填充错误消息 我正在测试是否在应用程序配置文件中输入了无效的脚本名称,我怀疑我使用的委托不正确。我的匿名委托由“新代码”和现有类方法的组合组成。我认为这是错误的;如果你们能把我推到一个地方,我会很感激的;) 注意:这个.copy_s

在下面的代码中,我使用进程对象来执行一系列DOS批处理文件。 举个例子,我正在缩短脚本列表

后续(1+)脚本通过事件处理程序(而不是for循环)执行。这样,每个后续脚本仅在前一个脚本完成时运行。现在,由于某种原因,在执行第二个脚本时,我无法获取捕获到的异常以在状态栏中填充错误消息

我正在测试是否在应用程序配置文件中输入了无效的脚本名称,我怀疑我使用的委托不正确。我的匿名委托由“新代码”和现有类方法的组合组成。我认为这是错误的;如果你们能把我推到一个地方,我会很感激的;)

注意:这个.copy_scripts[]是由“goodname.bat,nosuchscript.bat”拆分而成的


我认为,与其使用事件来设置并继续循环,不如使用回调方法创建一个异步委托。流程完成后,只需再次调用
RunCopyScript(…)
。看一看。我肯定有人会用
动作
来做这件事,我只是不太清楚,不能给你举个例子

我还看到了一个关于如何将输出从跨线程函数导入gui控件元素的简洁片段。不幸的是,我找不到我之前看到的优雅的代码……如果我遇到它,我会发布一个链接到它

好吧,这就是我所拥有的——为了它的价值。我相信这是相当准确的。我不希望它会开箱即用地编译,因为我没有所有的文件、路径等来正确启动进程。将模拟批处理文件设置为
Start()
a
Process
将需要更多的工作。我希望你应该能够与此工作,并有一些更接近你想要的东西,如果交叉引用我上面提供的链接

我还注释掉了一些不需要的代码行,我移动了,或者没有被识别。此外,我没有对您当前的
try/catch
块执行任何操作

// same signature as the method to be called asynchronously
delegate void RunScript(Int32 scriptIdx);

// declare IAsyncResult
IAsyncResult result;

Process proc = null;

private void copybutton_Click(object sender , EventArgs e)
{
    InitializeBar();

    nbr_of_copy_exits_ = 0;
    //this.RunCopyScript(this.nbr_of_copy_exits_);
    RunScript start = new RunScript(RunCopyScript);

    result = start.BeginInvoke(nbr_of_copy_exits_ , new AsyncCallback(CopyExited) , proc);
    copybutton.Enabled = false  // you don't want the button to be clicked again.
}

private void RunCopyScript(Int32 CopyScriptIdx)
{
    try
    {
        proc = ObtainProcess(client_dest_dir_ + copy_scripts_[CopyScriptIdx]);
        proc.EnableRaisingEvents = true;
        //proc.Exited += new EventHandler(CopyExited);
        proc.Start();
        progressBar.Value = ProgressInPercent(copy_scripts_.Count() , CopyScriptIdx);
    }
    catch (Exception ex)
    {
        UpdateControl(this.toolStripStatusLabel1, "Error involving " + copy_scripts_[CopyScriptIdx] + ": " + 
            ex.Message);
        copybutton.BackColor = Color.Red;
    }
    //return;
}

void CopyExited(IAsyncResult iaRes)
{
    AsyncResult result = (AsyncResult)iaRes;
    RunScript caller = (RunScript)result.AsyncDelegate;

    Process senderProcess = (Process)iaRes.AsyncState;
    caller.EndInvoke(iaRes);

    if (++this.nbr_of_copy_exits_ == this.copy_scripts_.Count())
    {
        UpdateControl(toolStripStatusLabel1 , "Copying COMPLETE.");
        copybutton.Enabled = true;   // enable the button now that we're done
    }
    else
    {
        // start the process all over again
        iaRes = caller.BeginInvoke(this.nbr_of_copy_exits_ , new AsyncCallback(CopyExited) , proc);
    }
}

private void UpdateControl(ToolStripStatusLabel tssl , String text)
{
    Invoke((MethodInvoker)delegate
    {
        tssl.Text = text;
        progressBar.Value = 0;
    });

    //tssl.Refresh();  'System.Windows.Forms.ToolStripStatusLabel' does not contain a definition for 'Refresh'...
}

正如我所说的,有更多优雅的使用动作委托的实现,我确信它们可以是异步的。我希望有人能举个例子。

太好了,谢谢你的工作。我试过你的方法,不幸的是得到了同样的结果。但是您的方法使用了我还没有用到的东西:Begin/EndInvoke、委托定义、IAsync等等。我相信很快就会用到它们。谢谢。@Joe:我不确定我能帮到你有多近,但我认为这可能值得一试。这绝对是值得的。我将用一个尚未解决的小问题(即,应用程序配置文件一开始不太可能更改,更不用说其中有无效条目)来换取一种新的处理方式。这是我绝对会使用的好信息。我们“自欺欺人”需要团结一致。这并不容易,不是吗;)
// same signature as the method to be called asynchronously
delegate void RunScript(Int32 scriptIdx);

// declare IAsyncResult
IAsyncResult result;

Process proc = null;

private void copybutton_Click(object sender , EventArgs e)
{
    InitializeBar();

    nbr_of_copy_exits_ = 0;
    //this.RunCopyScript(this.nbr_of_copy_exits_);
    RunScript start = new RunScript(RunCopyScript);

    result = start.BeginInvoke(nbr_of_copy_exits_ , new AsyncCallback(CopyExited) , proc);
    copybutton.Enabled = false  // you don't want the button to be clicked again.
}

private void RunCopyScript(Int32 CopyScriptIdx)
{
    try
    {
        proc = ObtainProcess(client_dest_dir_ + copy_scripts_[CopyScriptIdx]);
        proc.EnableRaisingEvents = true;
        //proc.Exited += new EventHandler(CopyExited);
        proc.Start();
        progressBar.Value = ProgressInPercent(copy_scripts_.Count() , CopyScriptIdx);
    }
    catch (Exception ex)
    {
        UpdateControl(this.toolStripStatusLabel1, "Error involving " + copy_scripts_[CopyScriptIdx] + ": " + 
            ex.Message);
        copybutton.BackColor = Color.Red;
    }
    //return;
}

void CopyExited(IAsyncResult iaRes)
{
    AsyncResult result = (AsyncResult)iaRes;
    RunScript caller = (RunScript)result.AsyncDelegate;

    Process senderProcess = (Process)iaRes.AsyncState;
    caller.EndInvoke(iaRes);

    if (++this.nbr_of_copy_exits_ == this.copy_scripts_.Count())
    {
        UpdateControl(toolStripStatusLabel1 , "Copying COMPLETE.");
        copybutton.Enabled = true;   // enable the button now that we're done
    }
    else
    {
        // start the process all over again
        iaRes = caller.BeginInvoke(this.nbr_of_copy_exits_ , new AsyncCallback(CopyExited) , proc);
    }
}

private void UpdateControl(ToolStripStatusLabel tssl , String text)
{
    Invoke((MethodInvoker)delegate
    {
        tssl.Text = text;
        progressBar.Value = 0;
    });

    //tssl.Refresh();  'System.Windows.Forms.ToolStripStatusLabel' does not contain a definition for 'Refresh'...
}