عملية المعلقة عند تشغيل مع صافي Process.Start - ما هو الخطأ؟

StackOverflow https://stackoverflow.com/questions/439617

  •  22-07-2019
  •  | 
  •  

سؤال

وكتبت مجمع سريعة وقذرة حول svn.exe لاسترداد بعض المحتويات وتفعل شيئا معها، ولكن بالنسبة لبعض المدخلات من حين لآخر وبتكاثر معلقة ولن تنتهي. على سبيل المثال، مكالمة واحدة هي لائحة إس:

svn list "http://myserver:84/svn/Documents/Instruments/" --xml  --no-auth-cache --username myuser --password mypassword

وسطر الأوامر هذا يعمل بشكل جيد عندما كنت مجرد القيام بذلك من قذيفة الأوامر، ولكنه توقف في تطبيقي. بلدي ج # رمز لتشغيل هذا هو:

string cmd = "svn.exe";
string arguments = "list \"http://myserver:84/svn/Documents/Instruments/\" --xml  --no-auth-cache --username myuser --password mypassword";
int ms = 5000;
ProcessStartInfo psi = new ProcessStartInfo(cmd);
psi.Arguments = arguments;
psi.RedirectStandardOutput = true;
psi.WindowStyle = ProcessWindowStyle.Normal;
psi.UseShellExecute = false;
Process proc = Process.Start(psi);
StreamReader output = new StreamReader(proc.StandardOutput.BaseStream, Encoding.UTF8);

proc.WaitForExit(ms);
if (proc.HasExited)
{
    return output.ReadToEnd();
}

وهذا يأخذ كامل 5000 مللي ثانية وينتهي أبدا. تمديد الوقت لا يساعد. في موجه الأوامر منفصل، فإنه يعمل على الفور، لذلك أنا متأكد من أنها لا علاقة لها وقت الانتظار غير كافية. لالمدخلات الأخرى، ولكن هذا يبدو للعمل بشكل جيد.

وكما أنني حاولت تشغيل CMD.EXE منفصل هنا (حيث إكس هو svn.exe وسائط عبارة عن سلسلة ARG الأصلية)، ولكن لا يزال على تعليق حدث:

string cmd = "cmd";
string arguments = "/S /C \"" + exe + " " + args + "\"";

وماذا يمكن أن يكون الشد هنا، وكيف يمكنني تصحيح هذه الاشياء العملية الخارجي؟

وتحرير:

وأنا الآن فقط الحصول على جميع أنحاء لمعالجة هذا الأمر. MUCHO بفضل جون السكيت على اقتراحه، الذي يعمل في الواقع كبيرة. لدي سؤال آخر حول لي طريقة للتعامل مع هذا، وإن كان، لأن أنا متعددة الخيوط مبتدئ. أود اقتراحات حول تحسين أي قصور الصارخة أو أي شيء البكم خلاف ذلك. انتهى بي المطاف خلق طبقة صغيرة التي تحتوي على تيار المعياري، وب StringBuilder لعقد الإخراج، وعلم أن أقول عندما انتهى ذلك. ثم اعتدت ThreadPool.QueueUserWorkItem ومرت في مثيل صفي:

ProcessBufferHandler bufferHandler = new ProcessBufferHandler(proc.StandardOutput.BaseStream,
                                                                          Encoding.UTF8);
ThreadPool.QueueUserWorkItem(ProcessStream, bufferHandler);

proc.WaitForExit(ms);
if (proc.HasExited)
{
    bufferHandler.Stop();
    return bufferHandler.ReadToEnd();
}

و... و ...

private class ProcessBufferHandler
{
    public Stream stream;
    public StringBuilder sb;
    public Encoding encoding;
    public State state;

    public enum State
    {
        Running,
        Stopped
    }

    public ProcessBufferHandler(Stream stream, Encoding encoding)
    {
        this.stream = stream;
        this.sb = new StringBuilder();
        this.encoding = encoding;
        state = State.Running;
    }
    public void ProcessBuffer()
    {
        sb.Append(new StreamReader(stream, encoding).ReadToEnd());
    }

    public string ReadToEnd()
    {
        return sb.ToString();
    }

    public void Stop()
    {
        state = State.Stopped;
    }
}

ويبدو أن هذا العمل، ولكن أنا المشكوك فيه أن هذا هو أفضل وسيلة. هل هذا معقول؟ وماذا يمكنني أن أفعل لتحسينه؟

هل كانت مفيدة؟

المحلول

وقضية واحدة القياسية: هذه العملية يمكن أن تنتظر منك أن تقرأ انتاجها. إنشاء موضوع مستقل لقراءة من انتاجها القياسية بينما كنت في انتظار ذلك للخروج. انها قليلا من الألم، ولكن هذا قد يكون مشكلة.

نصائح أخرى

وجون السكيت حق على المال!

إذا كنت لا تمانع في الاقتراع بعد إطلاق قيادة إس الخاص بك حاول هذا:

Process command = new Process();
command.EnableRaisingEvents = false;
command.StartInfo.FileName = "svn.exe";
command.StartInfo.Arguments = "your svn arguments here";
command.StartInfo.UseShellExecute = false;
command.StartInfo.RedirectStandardOutput = true;
command.Start();

while (!command.StandardOutput.EndOfStream)
{
    Console.WriteLine(command.StandardOutput.ReadLine());
}

وكان لي لإسقاط إكس على جهاز العميل واستخدام Process.Start لإطلاقه.

وتطبيق الاستدعاء سوف يتعطل - أغلقت القضية حتى يتم آلة من افتراض أن إكس خطير وتمنع التطبيقات الأخرى من البدء بتشغيله

.

وانقر على الحق في إكس، وانتقل إلى خصائص. ضرب "الحظر" باتجاه الجزء السفلي بجانب تحذير الأمان.

وأنا أعلم أن هذه هي وظيفة القديمة ولكن ربما هذا سوف يساعد شخص ما. أنا استخدم هذا لتنفيذ بعض AWS <م> (الأمازون خدمات ويب) الأوامر CLI باستخدام المهام صافي TPL.

وفعلت شيئا من هذا القبيل في تنفيذ أمري التي يتم تنفيذها ضمن TPL العمل صافي والذي يتم إنشاؤه داخل بلدي WinForm خلفية طريقة عامل bgwRun_DoWork الذي عقد حلقة مع while(!bgwRun.CancellationPending). هذا يحتوي على قراءة معيار الناتج عن عملية عبر مشاركة جديدة باستخدام فئة صافي ThreadPool.

private void bgwRun_DoWork(object sender, DoWorkEventArgs e)
{
  while (!bgwRun.CancellationPending)
  {
   //build TPL Tasks
   var tasks = new List<Task>();

   //work to add tasks here

   tasks.Add(new Task(()=>{

     //build .Net ProcessInfo, Process and start Process here

     ThreadPool.QueueUserWorkItem(state =>
       {
           while (!process.StandardOutput.EndOfStream)
           {
               var output = process.StandardOutput.ReadLine();
               if (!string.IsNullOrEmpty(output))
               {
                   bgwRun_ProgressChanged(this, new ProgressChangedEventArgs(0, new ExecutionInfo
                   {
                       Type = "ExecutionInfo",
                       Text = output,
                       Configuration = s3SyncConfiguration
                   }));
               }

               if (cancellationToken.GetValueOrDefault().IsCancellationRequested)
               {
                     break;
               }
           }
       });
   });//work Task

   //loop through and start tasks here and handle completed tasks

  } //end while
}

وأنا أعلم أن بلدي اتفاقيات إعادة الشراء SVN تشغيل بطيئة في بعض الأحيان، لذلك ربما 5 ثوان ليست طويلة بما فيه الكفاية؟ هل نسخ السلسلة التي يتم تمريرها إلى العملية من نقطة فاصل حتى كنت إيجابية انها ليست المطالبة بأي شيء؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top