Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/339.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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# 几个信号器调用使UI没有响应_C#_Multithreading_User Interface_Signalr - Fatal编程技术网

C# 几个信号器调用使UI没有响应

C# 几个信号器调用使UI没有响应,c#,multithreading,user-interface,signalr,C#,Multithreading,User Interface,Signalr,我们有一个任务调度器应用程序的这个执行方法,它处理一个进程(System.Diagnostics)收到的输出字符串: SendOutput方法通过信号器将输出发送到UI 问题是,当流程运行一个生成多个输出的命令时,它还会对UI进行多个信号器调用,从而使其锁定 首先,我使用setTimeout Javascript方法解决了UI问题。它不再锁定,但由于一系列超时,它延长了输出的显示时间 我认为处理这些输出的最好方法是通过服务器端,在一段时间内(比如说1到2秒)连接一系列输出,然后将它们发送到UI。

我们有一个任务调度器应用程序的这个执行方法,它处理一个进程(System.Diagnostics)收到的输出字符串:

SendOutput方法通过信号器将输出发送到UI

问题是,当流程运行一个生成多个输出的命令时,它还会对UI进行多个信号器调用,从而使其锁定

首先,我使用setTimeout Javascript方法解决了UI问题。它不再锁定,但由于一系列超时,它延长了输出的显示时间

我认为处理这些输出的最好方法是通过服务器端,在一段时间内(比如说1到2秒)连接一系列输出,然后将它们发送到UI。我倾向于使用计时器或任务。延迟,但我不能清楚地构建它


希望有人能帮上忙。

计时器会帮你分类的。这里有一些代码可以做到这一点(因为我没有得到你的基类)。这在控制台中运行,因此很明显,您必须执行一些工作,例如删除对控制台的调用。这些呼叫都在那里,因此您可以在控制台应用程序中进行测试。这里的SendOutput方法只是写入控制台,但您只需删除它,它就应该调用您的signalR客户端

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Timers;

namespace bufferOutput
{
    public class Processor
    {
        private object bufferLock = new object();
        private StringBuilder sb = new StringBuilder();
        private Timer updateTime = new Timer(250);//fire every quarter second: a reasonable time for a web page to update

        public void Execute(string fileName, string args)
        {
            var process = new Process { StartInfo = { FileName = fileName, Arguments = args } };
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardError = true;
            process.EnableRaisingEvents = true;
            process.Exited += ProcessExited;
            process.OutputDataReceived += AppendOutput;
            process.Start();
            updateTime.Elapsed += updateTime_Elapsed;
            process.BeginOutputReadLine();
            updateTime.Start();
            Console.Title = "Buffered data: Press the Enter key to exit the program.";
            Console.ReadLine();
            ProcessExited(this, EventArgs.Empty);
            Console.ReadLine();
        }

        void updateTime_Elapsed(object sender, ElapsedEventArgs e)
        {
            string output = "";
            lock(bufferLock)
            {
                output = sb.ToString();
                if (output != "")//if there was anything in the strng builder, clear it
                    sb = new StringBuilder();
            }
            if (output != "")
                SendOutput(output);
        }

        public void ProcessExited(object sender, EventArgs e)
        {
            updateTime.Stop();
            Console.Title = "writing out buffer: Press the Enter key to exit the program.";
            updateTime_Elapsed(this, null);
            SendOutput("Done");
        }

        public void AppendOutput(object sender, DataReceivedEventArgs e)
        {
            if (e.Data != null)
            {
                lock (bufferLock)
                    sb.AppendLine(e.Data);
            }
        }

        public void SendOutput(string output)//placeholder for the client side
        {
            Console.WriteLine(output);
        }
    }
}

看起来您正在将类锁定在进程的输出数据接收事件处理程序中,这可能不是最好的主意

计时器应该为您排序。这里有一些代码可以做到这一点(因为我没有得到你的基类)。这在控制台中运行,因此很明显,您必须执行一些工作,例如删除对控制台的调用。这些呼叫都在那里,因此您可以在控制台应用程序中进行测试。这里的SendOutput方法只是写入控制台,但您只需删除它,它就应该调用您的signalR客户端

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Timers;

namespace bufferOutput
{
    public class Processor
    {
        private object bufferLock = new object();
        private StringBuilder sb = new StringBuilder();
        private Timer updateTime = new Timer(250);//fire every quarter second: a reasonable time for a web page to update

        public void Execute(string fileName, string args)
        {
            var process = new Process { StartInfo = { FileName = fileName, Arguments = args } };
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardError = true;
            process.EnableRaisingEvents = true;
            process.Exited += ProcessExited;
            process.OutputDataReceived += AppendOutput;
            process.Start();
            updateTime.Elapsed += updateTime_Elapsed;
            process.BeginOutputReadLine();
            updateTime.Start();
            Console.Title = "Buffered data: Press the Enter key to exit the program.";
            Console.ReadLine();
            ProcessExited(this, EventArgs.Empty);
            Console.ReadLine();
        }

        void updateTime_Elapsed(object sender, ElapsedEventArgs e)
        {
            string output = "";
            lock(bufferLock)
            {
                output = sb.ToString();
                if (output != "")//if there was anything in the strng builder, clear it
                    sb = new StringBuilder();
            }
            if (output != "")
                SendOutput(output);
        }

        public void ProcessExited(object sender, EventArgs e)
        {
            updateTime.Stop();
            Console.Title = "writing out buffer: Press the Enter key to exit the program.";
            updateTime_Elapsed(this, null);
            SendOutput("Done");
        }

        public void AppendOutput(object sender, DataReceivedEventArgs e)
        {
            if (e.Data != null)
            {
                lock (bufferLock)
                    sb.AppendLine(e.Data);
            }
        }

        public void SendOutput(string output)//placeholder for the client side
        {
            Console.WriteLine(output);
        }
    }
}

看起来您正在将类锁定在进程的输出数据接收事件处理程序中,这可能不是最好的主意

谢谢你的努力,凯尔。我现在正在使用计时器,但我仍在检查您的示例以进行比较。我可以知道为什么我的代码中的当前锁不是一件好事吗?看起来你的类被称为ExecutionContext,所以你有效地锁定了类型。如果它是公共类型,这可能是一个问题,因为任何东西都可能锁定它并导致死锁。您通常希望锁定线程安全类中的私有对象以防止这种死锁。我使用秒表,但逻辑是相同的。再次谢谢你,凯尔,谢谢你的努力,凯尔。我现在正在使用计时器,但我仍在检查您的示例以进行比较。我可以知道为什么我的代码中的当前锁不是一件好事吗?看起来你的类被称为ExecutionContext,所以你有效地锁定了类型。如果它是公共类型,这可能是一个问题,因为任何东西都可能锁定它并导致死锁。您通常希望锁定线程安全类中的私有对象以防止这种死锁。我使用秒表,但逻辑是相同的。再次感谢你,凯尔。