প্রসেসস্টার্টআইফোন "ওয়েটফরেক্সট" এ ঝুলছে? কেন?


186

আমার কাছে নিম্নলিখিত কোড রয়েছে:

info = new System.Diagnostics.ProcessStartInfo("TheProgram.exe", String.Join(" ", args));
info.CreateNoWindow = true;
info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
System.Diagnostics.Process p = System.Diagnostics.Process.Start(info);
p.WaitForExit();
Console.WriteLine(p.StandardOutput.ReadToEnd()); //need the StandardOutput contents

আমি জানি যে প্রক্রিয়াটি শুরু করছি তার ফলাফল আউটপুট প্রায় 7MB দীর্ঘ। এটি উইন্ডোজ কনসোলে চালানো ভাল কাজ করে। দুর্ভাগ্যক্রমে প্রোগ্রামগতভাবে এটি ওয়েটফরএক্সিট-এ অনির্দিষ্ট সময়ের জন্য স্থির থাকে। এটিও নোট করুন ছোট আউটপুটগুলির জন্য (3KB এর মতো) কোডটি স্থগিত করে না।

এটি কি সম্ভব যে প্রসেসস্টার্টআইএনফোতে অভ্যন্তরীণ স্ট্যান্ডার্ডআউটপুট 7 এমবি বাফার করতে পারে না? যদি তা হয় তবে এর পরিবর্তে আমার কী করা উচিত? তা না হলে আমি কী ভুল করছি?


এটি সম্পর্কে সম্পূর্ণ উত্স কোড সহ কোনও চূড়ান্ত সমাধান?
কিকিনেট

2
আমি একই সমস্যা পাতিত করা এবং এই কিভাবে আমি এটা সমাধান করতে সক্ষম হন stackoverflow.com/questions/2285288/...
Bedasso

6
হ্যাঁ, চূড়ান্ত সমাধান: শেষ দুটি লাইনটি অদলবদল করুন। এটি ম্যানুয়ালটিতে রয়েছে
অমিত নাইডু

4
এমএসডিএন থেকে: কোড উদাহরণটি পি.স্ট্যান্ডার্ডআউটপুট কল করে একটি অচলাবস্থার পরিস্থিতি এড়ায় p যদি পিতামহী প্রসেস পি। স্ট্যান্ডার্ডআউটপুট এর আগে p.WaitforExit কল করে তবে একটি অচলাবস্থার পরিণতি ঘটতে পারে e রিডটোইন্ড এবং শিশু প্রক্রিয়া পুনঃনির্দেশিত স্ট্রিমটি পূরণ করার জন্য পর্যাপ্ত পাঠ্য লেখায়। সন্তানের প্রক্রিয়াটি প্রস্থান করার জন্য পিতামাতার প্রক্রিয়া অনির্দিষ্টকালের জন্য অপেক্ষা করবে। সন্তানের প্রক্রিয়াটি সম্পূর্ণ স্ট্যান্ডার্ডআউটপুট স্ট্রিম থেকে পিতামাতার পড়ার জন্য অনির্দিষ্টকালের জন্য অপেক্ষা করবে।
কার্লোস লিউ

এটি সঠিকভাবে এটি করা কতটা জটিল তা কিছুটা বিরক্তিকর। সরল কমান্ড লাইন পুনঃনির্দেশ> আউটপুটফিল :) এর সাথে কাজ করে খুশি হয়েছিল :)
এলাশিয়াস

উত্তর:


392

সমস্যাটি হ'ল আপনি যদি পুনর্নির্দেশ করেন StandardOutputএবং / অথবা StandardErrorঅভ্যন্তরীণ বাফার পূর্ণ হতে পারে। আপনি যে কোনও আদেশ ব্যবহার করুন না কেন, সমস্যা হতে পারে:

  • প্রক্রিয়াটি পড়ার আগে যদি আপনি প্রক্রিয়াটি প্রস্থান হওয়ার অপেক্ষায় থাকেন তবে প্রক্রিয়াটি StandardOutputলেখার চেষ্টাটিকে আটকাতে পারে, সুতরাং প্রক্রিয়াটি কখনও শেষ হয় না।
  • আপনি যদি StandardOutputReadToEnd ব্যবহার থেকে পড়ে থাকেন তবে প্রক্রিয়াটি কখনই বন্ধ না হলে আপনার প্রক্রিয়াটি ব্লক করতে পারে StandardOutput(উদাহরণস্বরূপ যদি এটি কখনও অবসান হয় না, বা যদি এটিতে লেখা অবরুদ্ধ থাকে StandardError)।

সমাধানটি হ'ল অ্যাসিঙ্ক্রোনাস রিডগুলি নিশ্চিত করে তা নিশ্চিত করতে বাফারটি পূর্ণ না হয় use কোনও অচলাবস্থা এড়াতে এবং উভয় থেকে সমস্ত আউটপুট সংগ্রহ করতে StandardOutputএবং StandardErrorআপনি এটি করতে পারেন:

সম্পাদনা: সময়সীমা শেষ হলে কীভাবে কোনও অবজেক্টডিসপোজড এক্সপেকশন এড়ানো যায় তার জন্য নীচের উত্তরগুলি দেখুন ।

using (Process process = new Process())
{
    process.StartInfo.FileName = filename;
    process.StartInfo.Arguments = arguments;
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.RedirectStandardError = true;

    StringBuilder output = new StringBuilder();
    StringBuilder error = new StringBuilder();

    using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
    using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
    {
        process.OutputDataReceived += (sender, e) => {
            if (e.Data == null)
            {
                outputWaitHandle.Set();
            }
            else
            {
                output.AppendLine(e.Data);
            }
        };
        process.ErrorDataReceived += (sender, e) =>
        {
            if (e.Data == null)
            {
                errorWaitHandle.Set();
            }
            else
            {
                error.AppendLine(e.Data);
            }
        };

        process.Start();

        process.BeginOutputReadLine();
        process.BeginErrorReadLine();

        if (process.WaitForExit(timeout) &&
            outputWaitHandle.WaitOne(timeout) &&
            errorWaitHandle.WaitOne(timeout))
        {
            // Process completed. Check process.ExitCode here.
        }
        else
        {
            // Timed out.
        }
    }
}

11
আউটপুটটিকে পুনঃনির্দেশিত করার কারণে সমস্যাটির কারণ হচ্ছিল না তবে যথেষ্ট ছিল তা নিশ্চিত। এটিতে আমার মাথার ঘাড়ে 4 ঘন্টা ব্যয় করুন এবং আপনার পোস্টটি পড়ার পরে 5 মিনিটের মধ্যে এটি স্থির করে fixed চমৎকার কাজ!
বেন গ্রিপকা

1
@ অ্যালেক্সপেক সমস্যাটি এটি একটি কনসোল অ্যাপ্লিকেশন হিসাবে চলছিল। হান্স পাসেন্ট এখানে বিষয়টি চিহ্নিত করেছেন: stackoverflow.com/a/16218470/279516
বব হর্ন

5
কমান্ড প্রম্পটটি বন্ধ হওয়ার সাথে সাথে এটি প্রদর্শিত হয়: "সিস্টেম.অজেক্টডিস্পোজড" টাইপের একটি অপ্রত্যাশিত ব্যতিক্রমটি এমএসসিআরলিবি.ডিলিতে ঘটেছিল অতিরিক্ত তথ্য: নিরাপদ হ্যান্ডেলটি বন্ধ করা হয়েছে
ব্যবহারকারী 1663380

3
উপরে @ ব্যবহারকারী 1663380 দ্বারা বর্ণিত হিসাবে আমাদের একই সমস্যা ছিল। আপনি কি মনে করেন যে usingইভেন্ট হ্যান্ডলারের পক্ষে বিবৃতি প্রক্রিয়াটির জন্যই বিবৃতিটির উপরে হওয়া উচিত using?
ড্যান ফোর্বস

2
আমি মনে করি না অপেক্ষা করার হাতলগুলি দরকার। এমএসডিএন অনুসারে ওয়েটফরএক্সিট-এর অ-সময়সীমার সংস্করণটি শেষ করুন: যখন স্ট্যান্ডার্ড আউটপুট অ্যাসিঙ্ক্রোনাস ইভেন্ট হ্যান্ডলারগুলিতে পুনঃনির্দেশিত করা হয় তখন সম্ভব হয় যে এই পদ্ধতিটি ফিরে আসার পরে আউটপুট প্রক্রিয়াকরণ সম্পন্ন হবে না। অ্যাসিঙ্ক্রোনাস ইভেন্ট হ্যান্ডলিং সম্পন্ন হয়েছে তা নিশ্চিত করার জন্য, এই ওভারলোড থেকে সত্য পাওয়ার পরে কোনও পরামিতি নেয় না এমন ওয়েটফরেক্সট () ওভারলোডকে কল করুন।
প্যাট্রিক

98

এর জন্য ডকুমেন্টেশনগুলিProcess.StandardOutput অপেক্ষা করার আগে পড়তে বলছে অন্যথায় আপনি অচল করে দিতে পারেন, স্নিপেটটি নীচে অনুলিপি করেছেন:

 // Start the child process.
 Process p = new Process();
 // Redirect the output stream of the child process.
 p.StartInfo.UseShellExecute = false;
 p.StartInfo.RedirectStandardOutput = true;
 p.StartInfo.FileName = "Write500Lines.exe";
 p.Start();
 // Do not wait for the child process to exit before
 // reading to the end of its redirected stream.
 // p.WaitForExit();
 // Read the output stream first and then wait.
 string output = p.StandardOutput.ReadToEnd();
 p.WaitForExit();

14
আমি যদি 100% নিশ্চিত নই তবে এটি আমার পরিবেশের ফলাফল মাত্র, তবে আমি খুঁজে পেলাম যে আপনি সেট করে রেখেছেন RedirectStandardOutput = true;এবং ব্যবহার না করলে আপনাকে p.StandardOutput.ReadToEnd();একটি অচলাবস্থা / হ্যাং পাবেন।
ক্রিস এস

3
সত্য। আমিও একই রকম অবস্থায় ছিলাম। কোনও প্রক্রিয়ায় ffmpeg- র সাথে রূপান্তর করার সময় আমি অকারণে স্ট্যান্ডার্ডআরারকে পুনঃনির্দেশ করছিলাম, এটি একটি অচলাবস্থা তৈরির জন্য স্ট্যান্ডার্ডআরার স্ট্রিমে যথেষ্ট লিখেছিল।
লিয়ন পেলেটিয়ার

পুনঃনির্দেশ এবং স্ট্যান্ডার্ড আউটপুট পড়ার পরেও এটি আমার জন্য স্তব্ধ।
ব্যবহারকারী 3791372

@ ব্যবহারকারী 937৯১7272২ আমার ধারণা, স্ট্যান্ডার্ডআউটপুটটির পিছনে বাফার পুরোপুরি পূরণ না হলে এটি কেবলমাত্র প্রযোজ্য। এখানে এমএসডিএন তার ন্যায়বিচার করে না। একটি দুর্দান্ত নিবন্ধ যা আমি আপনাকে পড়ার পরামর্শ দিচ্ছি তা হল: dzone.com/articles/async-io-and-threadpool
Cary

19

মার্ক বাইয়ার্সের উত্তরটি দুর্দান্ত, তবে আমি কেবল নিম্নলিখিতগুলি যুক্ত করব:

এর আগে OutputDataReceivedএবং ErrorDataReceivedপ্রতিনিধিদের অপসারণ outputWaitHandleএবং errorWaitHandleনিষ্পত্তি করার প্রয়োজন। যদি প্রক্রিয়াটি সময়সীমা অতিক্রম করার পরে আউটপুট ডেটা অবিরত করতে থাকে এবং তারপরে সমাপ্ত হয়, outputWaitHandleএবং errorWaitHandleভেরিয়েবলগুলি নিষ্পত্তি হওয়ার পরে অ্যাক্সেস করা হবে।

(এফওয়াইআইআই আমাকে তার পোস্টে মন্তব্য করতে না পারায় উত্তর হিসাবে এই সতর্কতা যুক্ত করতে হয়েছিল))



এই উত্তরে মার্কের সম্পাদিত কোড যুক্ত করা বরং দুর্দান্ত হবে! আমি ঠিক একই সমস্যাটি মুহুর্তে করছি।
আয়ানবেইলি

8
@ianbailey এর সমাধানের সহজতম উপায় হ'ল ব্যবহারের (প্রসেস পি ...) ব্যবহারের মধ্যে রাখা (AutoResetEvent ত্রুটিওয়াইটহ্যান্ডেল ...)
দিদিয়ার এ।

17

প্রক্রিয়াটির সময়সীমা শেষ হয়ে গেলে আনহ্যান্ডেল অবজেক্টডিস্পোজড এক্সপ্লেশন নিয়ে সমস্যাটি ঘটে। এই ক্ষেত্রে শর্তের অন্যান্য অংশগুলি:

if (process.WaitForExit(timeout) 
    && outputWaitHandle.WaitOne(timeout) 
    && errorWaitHandle.WaitOne(timeout))

মৃত্যুদণ্ড কার্যকর করা হয় না আমি এই সমস্যাটি নিম্নলিখিত উপায়ে সমাধান করেছি:

using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
{
    using (Process process = new Process())
    {
        // preparing ProcessStartInfo

        try
        {
            process.OutputDataReceived += (sender, e) =>
                {
                    if (e.Data == null)
                    {
                        outputWaitHandle.Set();
                    }
                    else
                    {
                        outputBuilder.AppendLine(e.Data);
                    }
                };
            process.ErrorDataReceived += (sender, e) =>
                {
                    if (e.Data == null)
                    {
                        errorWaitHandle.Set();
                    }
                    else
                    {
                        errorBuilder.AppendLine(e.Data);
                    }
                };

            process.Start();

            process.BeginOutputReadLine();
            process.BeginErrorReadLine();

            if (process.WaitForExit(timeout))
            {
                exitCode = process.ExitCode;
            }
            else
            {
                // timed out
            }

            output = outputBuilder.ToString();
        }
        finally
        {
            outputWaitHandle.WaitOne(timeout);
            errorWaitHandle.WaitOne(timeout);
        }
    }
}

1
সম্পূর্ণতার জন্য, এটি সত্যে পুনর্নির্দেশগুলি স্থাপন করা মিস করছে
নট করুন

এবং আমি আমার শেষের সময়সীমাটি সরিয়ে দিয়েছি যেহেতু প্রক্রিয়াটি ব্যবহারকারী ইনপুট চাইতে পারে (উদাহরণস্বরূপ কিছু টাইপ করুন) সুতরাং আমি ব্যবহারকারীকে দ্রুত হওয়া দরকার না
নোকট

কেন আপনি পরিবর্তিত হয়েছে outputএবং errorকরতে outputBuilder? কেউ দয়া করে কাজ করতে পারে এমন পুরো উত্তর প্রদান করতে পারেন?
মার্কো আলেলিš

সিস্টেম.অবজেক্ট ডিসপোজড এক্সসেপশন: নিরাপদ হ্যান্ডেলটি বন্ধ করা হয়েছে আমার জন্যও এই সংস্করণে
ম্যাট

17

এটি আরও আধুনিক প্রত্যাশিত, টাস্ক সমান্তরাল গ্রন্থাগার (টিপিএল) ভিত্তিক সমাধান .NET 4.5 এবং এর উপরের জন্য।

ব্যবহারের উদাহরণ

try
{
    var exitCode = await StartProcess(
        "dotnet", 
        "--version", 
        @"C:\",
        10000, 
        Console.Out, 
        Console.Out);
    Console.WriteLine($"Process Exited with Exit Code {exitCode}!");
}
catch (TaskCanceledException)
{
    Console.WriteLine("Process Timed Out!");
}

বাস্তবায়ন

public static async Task<int> StartProcess(
    string filename,
    string arguments,
    string workingDirectory= null,
    int? timeout = null,
    TextWriter outputTextWriter = null,
    TextWriter errorTextWriter = null)
{
    using (var process = new Process()
    {
        StartInfo = new ProcessStartInfo()
        {
            CreateNoWindow = true,
            Arguments = arguments,
            FileName = filename,
            RedirectStandardOutput = outputTextWriter != null,
            RedirectStandardError = errorTextWriter != null,
            UseShellExecute = false,
            WorkingDirectory = workingDirectory
        }
    })
    {
        var cancellationTokenSource = timeout.HasValue ?
            new CancellationTokenSource(timeout.Value) :
            new CancellationTokenSource();

        process.Start();

        var tasks = new List<Task>(3) { process.WaitForExitAsync(cancellationTokenSource.Token) };
        if (outputTextWriter != null)
        {
            tasks.Add(ReadAsync(
                x =>
                {
                    process.OutputDataReceived += x;
                    process.BeginOutputReadLine();
                },
                x => process.OutputDataReceived -= x,
                outputTextWriter,
                cancellationTokenSource.Token));
        }

        if (errorTextWriter != null)
        {
            tasks.Add(ReadAsync(
                x =>
                {
                    process.ErrorDataReceived += x;
                    process.BeginErrorReadLine();
                },
                x => process.ErrorDataReceived -= x,
                errorTextWriter,
                cancellationTokenSource.Token));
        }

        await Task.WhenAll(tasks);
        return process.ExitCode;
    }
}

/// <summary>
/// Waits asynchronously for the process to exit.
/// </summary>
/// <param name="process">The process to wait for cancellation.</param>
/// <param name="cancellationToken">A cancellation token. If invoked, the task will return
/// immediately as cancelled.</param>
/// <returns>A Task representing waiting for the process to end.</returns>
public static Task WaitForExitAsync(
    this Process process,
    CancellationToken cancellationToken = default(CancellationToken))
{
    process.EnableRaisingEvents = true;

    var taskCompletionSource = new TaskCompletionSource<object>();

    EventHandler handler = null;
    handler = (sender, args) =>
    {
        process.Exited -= handler;
        taskCompletionSource.TrySetResult(null);
    };
    process.Exited += handler;

    if (cancellationToken != default(CancellationToken))
    {
        cancellationToken.Register(
            () =>
            {
                process.Exited -= handler;
                taskCompletionSource.TrySetCanceled();
            });
    }

    return taskCompletionSource.Task;
}

/// <summary>
/// Reads the data from the specified data recieved event and writes it to the
/// <paramref name="textWriter"/>.
/// </summary>
/// <param name="addHandler">Adds the event handler.</param>
/// <param name="removeHandler">Removes the event handler.</param>
/// <param name="textWriter">The text writer.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>A task representing the asynchronous operation.</returns>
public static Task ReadAsync(
    this Action<DataReceivedEventHandler> addHandler,
    Action<DataReceivedEventHandler> removeHandler,
    TextWriter textWriter,
    CancellationToken cancellationToken = default(CancellationToken))
{
    var taskCompletionSource = new TaskCompletionSource<object>();

    DataReceivedEventHandler handler = null;
    handler = new DataReceivedEventHandler(
        (sender, e) =>
        {
            if (e.Data == null)
            {
                removeHandler(handler);
                taskCompletionSource.TrySetResult(null);
            }
            else
            {
                textWriter.WriteLine(e.Data);
            }
        });

    addHandler(handler);

    if (cancellationToken != default(CancellationToken))
    {
        cancellationToken.Register(
            () =>
            {
                removeHandler(handler);
                taskCompletionSource.TrySetCanceled();
            });
    }

    return taskCompletionSource.Task;
}

2
তারিখের সেরা এবং সর্বাধিক সম্পূর্ণ উত্তর
TermoTux

1
কিছু রিওনের জন্য, এটি আমার জন্য কাজ করা একমাত্র সমাধান ছিল, অ্যাপ্লিকেশনটি হ্যাঙ হওয়া বন্ধ করে দিয়েছে।
জ্যাক

1
দেখে মনে হচ্ছে, আপনি শর্তটি পরিচালনা করেন না, যেখানে প্রক্রিয়াটি শুরু হওয়ার পরে শেষ হয় তবে প্রস্থানিত ইভেন্টটি সংযুক্ত হওয়ার আগেই। আমার পরামর্শ - সমস্ত রেজিস্ট্রেশন পরে প্রক্রিয়া শুরু।
স্টাস বায়ারিনসেভ

@ স্ট্যাসবায়ারিন্সভ ধন্যবাদ, আপডেট হয়েছে। আমি এই পরিবর্তনটির সাথে স্ট্যাক ওভারফ্লো উত্তরটি আপডেট করতে ভুলে গিয়েছিলাম।
মুহাম্মদ রেহান সা Saeedদ

1
@ মুহম্মেদরহানসেইদ আর একটি বিষয় - এটি কল প্রক্রিয়া অনুমোদিত নয় বলে মনে হচ্ছে processআপনি.স্টার্টের আগেই বেসিনআউটপ্রেডলাইন () বা প্রক্রিয়া.বেগিনআরআরআরলাইন ()) এই ক্ষেত্রে আমি ত্রুটিটি পেয়েছি: স্ট্যান্ডার্ডআউট পুনর্নির্দেশ করা হয়নি বা প্রক্রিয়া এখনও শুরু হয়নি।
স্টাস বায়ার্নিঞ্জভ

8

রব এটির উত্তর দিয়েছিল এবং আরও কয়েক ঘন্টা ট্রায়াল সঞ্চয় করে। অপেক্ষা করার আগে আউটপুট / ত্রুটি বাফারটি পড়ুন:

// Read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();

1
আপনি ডেকে বলার পরেও যদি আরও ডেটা আসে WaitForExit()?
নোকট

আমার পরীক্ষার উপর ভিত্তি করে @ ননকোট, ReadToEndবা অনুরূপ পদ্ধতি (যেমন StandardOutput.BaseStream.CopyTo) সমস্ত ডেটা পড়ার পরে ফিরে আসবে । এর পরে আর কিছুই আসবে না
এস। স্পর্শান

আপনি বলছেন যে রিডটোএন্ড () এছাড়াও প্রস্থানটির জন্য অপেক্ষা করছে?
নোকট করুন

2
@knocte আপনি মাইক্রোসফ্ট দ্বারা নির্মিত একটি API বোঝার চেষ্টা করছেন?
aaaaaa

সংশ্লিষ্ট এমএসডিএন পৃষ্ঠার সমস্যাটি হ'ল, এটি ব্যাখ্যা করেনি যে স্ট্যান্ডার্ডআউটপুটটির পেছনের বাফারটি পূর্ণ হয়ে উঠতে পারে এবং সেই পরিস্থিতিতে শিশুটিকে লেখা বন্ধ করতে হবে এবং বাফারটি শুকানো অবধি অপেক্ষা করতে হবে (পিতামাতার বাফারে ডেটা পড়তে হবে) । বাফার বন্ধ না করা বা বাফার পূর্ণ না হওয়া পর্যন্ত বা বাফার পূর্ণ না হয়ে শিশু প্রস্থান না হওয়া অবধি রিডটোএন্ড () কেবলমাত্র সিঙ্ক-লইল পড়তে পারে। এটাই আমার বোঝাপড়া।
ক্যারি

7

আমাদেরও এই সমস্যাটি রয়েছে (বা বৈকল্পিক)।

নিম্নলিখিত চেষ্টা করুন:

1) পি.ওয়েটফরেক্সট (এনএনএন) এ একটি সময়সীমা যুক্ত করুন; যেখানে এনএনএন মিলি সেকেন্ডে রয়েছে।

2) ওয়েটফরএক্সিট কলের আগে রিডটোএন্ড কলটি দিন। এই হল আমরা যা দেখেছি মাইক্রোসফট সুপারিশ।


5

ক্রেডিট EM0 জন্য https://stackoverflow.com/a/17600012/4151626

অভ্যন্তরীণ সময়সীমা এবং স্বতঃপ্রযুক্ত অ্যাপ্লিকেশন দ্বারা স্ট্যান্ডার্ডআউটপুট এবং স্ট্যান্ডার্ডআরার উভয়ের ব্যবহারের কারণে অন্যান্য সমাধানগুলি (ইএম 0 সহ) এখনও আমার অ্যাপ্লিকেশনের জন্য অচল হয়ে পড়েছে। আমার জন্য যা কাজ করেছে তা এখানে:

Process p = new Process()
{
  StartInfo = new ProcessStartInfo()
  {
    FileName = exe,
    Arguments = args,
    UseShellExecute = false,
    RedirectStandardOutput = true,
    RedirectStandardError = true
  }
};
p.Start();

string cv_error = null;
Thread et = new Thread(() => { cv_error = p.StandardError.ReadToEnd(); });
et.Start();

string cv_out = null;
Thread ot = new Thread(() => { cv_out = p.StandardOutput.ReadToEnd(); });
ot.Start();

p.WaitForExit();
ot.Join();
et.Join();

সম্পাদনা: কোড নমুনায় স্টার্টইনফোর সূচনা যুক্ত করা হয়েছে


এটি আমি ব্যবহার করি এবং অচলাবস্থার সাথে আর কখনও সমস্যা হয়নি।
রোমের

3

আমি এটি এইভাবে সমাধান করেছি:

            Process proc = new Process();
            proc.StartInfo.FileName = batchFile;
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.CreateNoWindow = true;
            proc.StartInfo.RedirectStandardError = true;
            proc.StartInfo.RedirectStandardInput = true;
            proc.StartInfo.RedirectStandardOutput = true;
            proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;      
            proc.Start();
            StreamWriter streamWriter = proc.StandardInput;
            StreamReader outputReader = proc.StandardOutput;
            StreamReader errorReader = proc.StandardError;
            while (!outputReader.EndOfStream)
            {
                string text = outputReader.ReadLine();                    
                streamWriter.WriteLine(text);
            }

            while (!errorReader.EndOfStream)
            {                   
                string text = errorReader.ReadLine();
                streamWriter.WriteLine(text);
            }

            streamWriter.Close();
            proc.WaitForExit();

আমি ইনপুট, আউটপুট এবং ত্রুটি উভয়ই পুনঃনির্দেশ করেছি এবং আউটপুট এবং ত্রুটি স্ট্রিমগুলি থেকে পঠন পরিচালনা করি। এই সমাধানটি এসডিকে 7-8.1, উইন্ডোজ 7 এবং উইন্ডোজ 8 উভয়ের জন্যই কাজ করে


2
এলিনা: আপনার উত্তরের জন্য ধন্যবাদ। এই এমএসডিএন ডকের নীচে কিছু নোট রয়েছে (এমএসডিএন.মিকাইক্রোসফটকম / en-us / library/… ) যা আপনি পুনঃনির্দেশিত স্টডআউট এবং স্টার্ডার উভয় প্রবাহের সমলয়ভাবে পড়লে সম্ভাব্য ডেডলকগুলি সম্পর্কে সতর্ক করে। আপনার সমাধান এই ইস্যুতে সংবেদনশীল কিনা তা বলা শক্ত। এছাড়াও, এটি প্রদর্শিত হয় যে আপনি প্রক্রিয়াটির 'stdout / stderr আউটপুটটি সরাসরি ইনপুট হিসাবে প্রেরণ করছেন। কেন? :)
ম্যাথু পাইট

3

আমি একটি ক্লাস বানানোর চেষ্টা করেছি যা মার্ক বায়ার্স, রব, স্টিভজয় উত্তরগুলি অ্যাকাউন্টে রেখে অ্যাসিক্রোনাস স্ট্রিম রিড ব্যবহার করে আপনার সমস্যার সমাধান করবে। এটি করে আমি বুঝতে পেরেছি যে অ্যাসিনক্রোনাস প্রক্রিয়া আউটপুট স্ট্রিমের সাথে সম্পর্কিত একটি বাগ রয়েছে।

আমি এই বাগটি মাইক্রোসফ্টে জানিয়েছি: https://connect.microsoft.com/VisualStudio/feedback/details/3119134

সারসংক্ষেপ:

আপনি এটি করতে পারবেন না:

process.BeginOutputReadLine (); process.Start ();

আপনি সিস্টেমটি পাবেন I অবৈধ অপারেশন এক্সসেপশন: স্ট্যান্ডার্ডআউট পুনর্নির্দেশ করা হয়নি বা প্রক্রিয়া এখনও শুরু হয়নি।

================================================== ================================================== ========================

তারপরে প্রক্রিয়া শুরু হওয়ার পরে আপনাকে অ্যাসিঙ্ক্রোনাস আউটপুট পড়তে হবে:

process.Start (); process.BeginOutputReadLine ();

এটি করার কারণে, একটি রেসের শর্ত তৈরি করুন কারণ আউটপুট স্ট্রিমটি আপনি এ্যাসক্রোনাসে সেট করার আগে ডেটা পেতে পারে:

process.Start(); 
// Here the operating system could give the cpu to another thread.  
// For example, the newly created thread (Process) and it could start writing to the output
// immediately before next line would execute. 
// That create a race condition.
process.BeginOutputReadLine();

================================================== ================================================== ========================

তারপরে কিছু লোক বলতে পারে যে স্ট্রিমটিকে অ্যাসিঙ্ক্রোনাসে সেট করার আগে আপনাকে কেবল স্ট্রিমটি পড়তে হবে। তবে একই সমস্যা দেখা দেয়। সিঙ্ক্রোনাস রিড এবং স্ট্রিমটিকে অ্যাসিঙ্ক্রোনাস মোডে সেট করার মধ্যে একটি রেসের শর্ত থাকবে।

================================================== ================================================== ========================

"প্রক্রিয়া" এবং "প্রসেসস্টার্টআইএনফো" ডিজাইন করা হয়েছে এমন কোনও প্রক্রিয়ার আউটপুট স্ট্রিমের নিরাপদ অ্যাসিঙ্ক্রোনাস রিডের অ্যাকসিভ করার কোনও উপায় নেই।

আপনার ক্ষেত্রে অন্যান্য ব্যবহারকারীদের দ্বারা প্রস্তাবিত অ্যাসিনক্রোনাস রিডের মতো ব্যবহার করা আপনি সম্ভবত আরও ভাল। তবে আপনার সচেতন হওয়া উচিত যে রেসের শর্তের কারণে আপনি কিছু তথ্য মিস করতে পারেন।


1

আমি জানি যে এটি সহজ এবং ভাল পদ্ধতির (আমাদের প্রয়োজন নেই AutoResetEvent):

public static string GGSCIShell(string Path, string Command)
{
    using (Process process = new Process())
    {
        process.StartInfo.WorkingDirectory = Path;
        process.StartInfo.FileName = Path + @"\ggsci.exe";
        process.StartInfo.CreateNoWindow = true;
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.RedirectStandardInput = true;
        process.StartInfo.UseShellExecute = false;

        StringBuilder output = new StringBuilder();
        process.OutputDataReceived += (sender, e) =>
        {
            if (e.Data != null)
            {
                output.AppendLine(e.Data);
            }
        };

        process.Start();
        process.StandardInput.WriteLine(Command);
        process.BeginOutputReadLine();


        int timeoutParts = 10;
        int timeoutPart = (int)TIMEOUT / timeoutParts;
        do
        {
            Thread.Sleep(500);//sometimes halv scond is enough to empty output buff (therefore "exit" will be accepted without "timeoutPart" waiting)
            process.StandardInput.WriteLine("exit");
            timeoutParts--;
        }
        while (!process.WaitForExit(timeoutPart) && timeoutParts > 0);

        if (timeoutParts <= 0)
        {
            output.AppendLine("------ GGSCIShell TIMEOUT: " + TIMEOUT + "ms ------");
        }

        string result = output.ToString();
        return result;
    }
}

সত্য, তবে .FileName = Path + @"\ggsci.exe" + @" < obeycommand.txt"আপনার কোডটিও সহজ করার জন্য আপনার করা উচিত নয় ? অথবা "echo command | " + Path + @"\ggsci.exe"যদি আপনি সত্যিই একটি পৃথক आज्ञाদেশের আদেশ। Txt ফাইল ব্যবহার করতে না চান তবে এর সমতুল্য কিছু হতে পারে ।
অমিত নাইডু

3
আপনার সমাধানটির জন্য অটোসেটসেন্ট দরকার হয় না তবে আপনি পোল করেন। আপনি যখন ইভেন্ট ব্যবহারের পরিবর্তে পোল করেন (যখন সেগুলি উপলভ্য থাকে) তখন আপনি বিনা কারণে সিপিইউ ব্যবহার করছেন এবং এটি আপনাকে খারাপ প্রোগ্রামার বলে ইঙ্গিত দেয়। অটোসেটসেন্ট ব্যবহার করে অন্যের সাথে তুলনা করার সময় আপনার সমাধানটি সত্যই খারাপ। (তবে আমি আপনাকে -1 দেয়নি কারণ আপনি সাহায্য করার চেষ্টা করেছিলেন!)।
এরিক ওয়েললেট

1

উপরের উত্তরগুলির কোনওটিই কাজটি করছে না।

রব সলিউশন হ্যাং হয়ে যায় এবং 'মার্ক বাইয়ার্স' দ্রবণটি নিষ্পত্তিযোগ্য ব্যতিক্রম পায় ((আমি অন্যান্য উত্তরের "সমাধানগুলি" চেষ্টা করেছি)।

সুতরাং আমি অন্য সমাধানের পরামর্শ দেওয়ার সিদ্ধান্ত নিয়েছি:

public void GetProcessOutputWithTimeout(Process process, int timeoutSec, CancellationToken token, out string output, out int exitCode)
{
    string outputLocal = "";  int localExitCode = -1;
    var task = System.Threading.Tasks.Task.Factory.StartNew(() =>
    {
        outputLocal = process.StandardOutput.ReadToEnd();
        process.WaitForExit();
        localExitCode = process.ExitCode;
    }, token);

    if (task.Wait(timeoutSec, token))
    {
        output = outputLocal;
        exitCode = localExitCode;
    }
    else
    {
        exitCode = -1;
        output = "";
    }
}

using (var process = new Process())
{
    process.StartInfo = ...;
    process.Start();
    string outputUnicode; int exitCode;
    GetProcessOutputWithTimeout(process, PROCESS_TIMEOUT, out outputUnicode, out exitCode);
}

এই কোডটি ডিবাগ হয়েছে এবং পুরোপুরি কার্যকর হয়।


1
ভাল! কেবলমাত্র নোট করুন যে কল করার GetProcessOutputWithTimeoutপদ্ধতিতে টোকেন প্যারামিটার সরবরাহ করা হয় না ।
এস। সরপুশন

1

ভূমিকা

বর্তমানে গৃহীত উত্তরগুলি কাজ করে না (ব্যতিক্রম ছোঁড়ে) এবং অনেকগুলি কার্যপ্রণালী রয়েছে তবে সম্পূর্ণ কোড নেই। এটি স্পষ্টতই বহু লোকের সময় নষ্ট করছে কারণ এটি একটি জনপ্রিয় প্রশ্ন।

মার্ক বাইয়ার্সের উত্তর এবং করোল টাইলের উত্তরের সংমিশ্রণে আমি কীভাবে প্রসেস.স্টার্ট পদ্ধতিটি ব্যবহার করতে চাই তার উপর ভিত্তি করে আমি পুরো কোডটি লিখেছিলাম।

ব্যবহার

গিট কমান্ডের চারপাশে অগ্রগতি সংলাপ তৈরি করতে আমি এটি ব্যবহার করেছি। আমি এটি এইভাবে ব্যবহার করেছি:

    private bool Run(string fullCommand)
    {
        Error = "";
        int timeout = 5000;

        var result = ProcessNoBS.Start(
            filename: @"C:\Program Files\Git\cmd\git.exe",
            arguments: fullCommand,
            timeoutInMs: timeout,
            workingDir: @"C:\test");

        if (result.hasTimedOut)
        {
            Error = String.Format("Timeout ({0} sec)", timeout/1000);
            return false;
        }

        if (result.ExitCode != 0)
        {
            Error = (String.IsNullOrWhiteSpace(result.stderr)) 
                ? result.stdout : result.stderr;
            return false;
        }

        return true;
    }

তত্ত্বের ক্ষেত্রে আপনি স্টাডআউট এবং স্টডারকেও একত্রিত করতে পারেন, তবে আমি এটি পরীক্ষা করি নি।

কোড

public struct ProcessResult
{
    public string stdout;
    public string stderr;
    public bool hasTimedOut;
    private int? exitCode;

    public ProcessResult(bool hasTimedOut = true)
    {
        this.hasTimedOut = hasTimedOut;
        stdout = null;
        stderr = null;
        exitCode = null;
    }

    public int ExitCode
    {
        get 
        {
            if (hasTimedOut)
                throw new InvalidOperationException(
                    "There was no exit code - process has timed out.");

            return (int)exitCode;
        }
        set
        {
            exitCode = value;
        }
    }
}

public class ProcessNoBS
{
    public static ProcessResult Start(string filename, string arguments,
        string workingDir = null, int timeoutInMs = 5000,
        bool combineStdoutAndStderr = false)
    {
        using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
        using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
        {
            using (var process = new Process())
            {
                var info = new ProcessStartInfo();

                info.CreateNoWindow = true;
                info.FileName = filename;
                info.Arguments = arguments;
                info.UseShellExecute = false;
                info.RedirectStandardOutput = true;
                info.RedirectStandardError = true;

                if (workingDir != null)
                    info.WorkingDirectory = workingDir;

                process.StartInfo = info;

                StringBuilder stdout = new StringBuilder();
                StringBuilder stderr = combineStdoutAndStderr
                    ? stdout : new StringBuilder();

                var result = new ProcessResult();

                try
                {
                    process.OutputDataReceived += (sender, e) =>
                    {
                        if (e.Data == null)
                            outputWaitHandle.Set();
                        else
                            stdout.AppendLine(e.Data);
                    };
                    process.ErrorDataReceived += (sender, e) =>
                    {
                        if (e.Data == null)
                            errorWaitHandle.Set();
                        else
                            stderr.AppendLine(e.Data);
                    };

                    process.Start();

                    process.BeginOutputReadLine();
                    process.BeginErrorReadLine();

                    if (process.WaitForExit(timeoutInMs))
                        result.ExitCode = process.ExitCode;
                    // else process has timed out 
                    // but that's already default ProcessResult

                    result.stdout = stdout.ToString();
                    if (combineStdoutAndStderr)
                        result.stderr = null;
                    else
                        result.stderr = stderr.ToString();

                    return result;
                }
                finally
                {
                    outputWaitHandle.WaitOne(timeoutInMs);
                    errorWaitHandle.WaitOne(timeoutInMs);
                }
            }
        }
    }
}

তবুও সিস্টেমটি পান b অবজেক্ট ডিসপোজড এক্সপ্লেশন: নিরাপদ হ্যান্ডেলটিও এই সংস্করণে বন্ধ করা হয়েছে।
ম্যাট

1

আমি জানি যে এটি নৈশভোজ পুরাতন তবে পুরো পৃষ্ঠাটি পড়ার পরে আমার কোনও সমাধানই তার পক্ষে কাজ করছে না, যদিও আমি মুহাম্মদ রেহানকে কোডটি অনুসরণ করা একটু কঠিন বলে চেষ্টা করিনি, যদিও আমি অনুমান করি যে তিনি সঠিক পথে ছিলেন । যখন আমি বলি যে এটি পুরোপুরি সত্য নয়, এটি কাজ করে না, কখনও কখনও এটি ঠিক কাজ করবে, আমি অনুমান করি যে কোনও ইওএফ চিহ্নের আগে আউটপুটটির দৈর্ঘ্যের সাথে এটি করা কিছু।

যাইহোক, আমার জন্য যে সমাধানটি কাজ করেছিল তা হ'ল স্ট্যান্ডার্ডআউটপুট এবং স্ট্যান্ডার্ডএরর পড়তে এবং বার্তা লিখতে বিভিন্ন থ্রেড ব্যবহার করা।

        StreamWriter sw = null;
        var queue = new ConcurrentQueue<string>();

        var flushTask = new System.Timers.Timer(50);
        flushTask.Elapsed += (s, e) =>
        {
            while (!queue.IsEmpty)
            {
                string line = null;
                if (queue.TryDequeue(out line))
                    sw.WriteLine(line);
            }
            sw.FlushAsync();
        };
        flushTask.Start();

        using (var process = new Process())
        {
            try
            {
                process.StartInfo.FileName = @"...";
                process.StartInfo.Arguments = $"...";
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError = true;

                process.Start();

                var outputRead = Task.Run(() =>
                {
                    while (!process.StandardOutput.EndOfStream)
                    {
                        queue.Enqueue(process.StandardOutput.ReadLine());
                    }
                });

                var errorRead = Task.Run(() =>
                {
                    while (!process.StandardError.EndOfStream)
                    {
                        queue.Enqueue(process.StandardError.ReadLine());
                    }
                });

                var timeout = new TimeSpan(hours: 0, minutes: 10, seconds: 0);

                if (Task.WaitAll(new[] { outputRead, errorRead }, timeout) &&
                    process.WaitForExit((int)timeout.TotalMilliseconds))
                {
                    if (process.ExitCode != 0)
                    {
                        throw new Exception($"Failed run... blah blah");
                    }
                }
                else
                {
                    throw new Exception($"process timed out after waiting {timeout}");
                }
            }
            catch (Exception e)
            {
                throw new Exception($"Failed to succesfully run the process.....", e);
            }
        }
    }

আশা করি এটি এমন কাউকে সাহায্য করবে, যিনি ভাবেন যে এটি এত কঠিন হতে পারে!


ব্যতিক্রম: sw.FlushAsync(): Object is not set to an instance of an object. sw is null. কিভাবে / কোথায় swসংজ্ঞায়িত করা উচিত ?
wallyk

1

এখানে সমস্ত পোস্ট পড়ার পরে, আমি মার্কো অবলিজার একীভূত সমাধানে স্থির হয়েছি š তবে এটি আমার সমস্ত সমস্যার সমাধান করেনি।

আমাদের পরিবেশে আমাদের একটি উইন্ডোজ পরিষেবা রয়েছে যা কয়েকশ বছরের বিভিন্ন .bat .Cdd .exe, ... ইত্যাদি ফাইল চালানোর জন্য নির্ধারিত হয়েছে যা বছরের পর বছর ধরে জমে আছে এবং বিভিন্ন লোক এবং বিভিন্ন স্টাইলে লিখেছিল। প্রোগ্রামগুলি এবং স্ক্রিপ্টগুলি লেখার উপর আমাদের কোনও নিয়ন্ত্রণ নেই, আমরা সাফল্য / ব্যর্থতার সময়সূচী, চলমান এবং প্রতিবেদন করার জন্য কেবল দায়বদ্ধ।

তাই আমি সাফল্যের বিভিন্ন স্তরের সাথে এখানে পরামর্শগুলির বেশ কয়েকটি চেষ্টা করেছি। মার্কোর উত্তরটি প্রায় নিখুঁত ছিল, কিন্তু যখন পরিষেবা হিসাবে চালানো হয়, এটি সর্বদা স্টডআউটকে ক্যাপচার করেনি। আমি কখনই কেনো তলায় যাইনি।

একমাত্র সমাধান আমরা আমাদের সব ক্ষেত্রেই যে কাজ পাওয়া যায় নি এই হল: http://csharptest.net/319/using-the-processrunner-class/index.html


আমি এই লাইব্রেরি চেষ্টা করতে যাচ্ছি। আমি কোডটি বাদ দিয়েছি এবং এটি দেখে মনে হচ্ছে যে প্রতিনিধিরা সংবেদনশীলভাবে ব্যবহার করছেন। এটি নুগেটে সুন্দরভাবে প্যাকেজ করা আছে। এটি মূলত পেশাদারিত্বের দুর্গন্ধযুক্ত, এমন কিছু যা আমি কখনও দোষারোপ করতে পারি না। এটি কামড়ালে, বলবেন।
স্টিভ হিবার্ট

উত্স কোডের লিঙ্কটি মারা গেছে। পরবর্তী সময় উত্তরটি কোডটি অনুলিপি করুন।
ভাইটালি জাদানেভিচ

1

সমস্ত জটিলতা এড়াতে আমি শেষ হয়ে গেলাম:

var outputFile = Path.GetTempFileName();
info = new System.Diagnostics.ProcessStartInfo("TheProgram.exe", String.Join(" ", args) + " > " + outputFile + " 2>&1");
info.CreateNoWindow = true;
info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
info.UseShellExecute = false;
System.Diagnostics.Process p = System.Diagnostics.Process.Start(info);
p.WaitForExit();
Console.WriteLine(File.ReadAllText(outputFile)); //need the StandardOutput contents

সুতরাং আমি একটি টেম্প ফাইল তৈরি করি, এটির মাধ্যমে আউটপুট এবং ত্রুটি উভয়ই পুনর্নির্দেশ করি > outputfile > 2>&1এবং প্রক্রিয়াটি শেষ হওয়ার পরে কেবল ফাইলটি পড়ি।

অন্যান্য সমাধানগুলি পরিস্থিতিতে যেখানে আপনি আউটপুট সহ অন্যান্য স্টাফগুলি করতে চান তা সূক্ষ্ম, তবে সাধারণ স্টাফের জন্য এটি অনেক জটিলতা এড়ায়।


1

আমি অনেক উত্তর পড়েছি এবং নিজের তৈরি করেছি। নিশ্চিত না যে এটি কোনও ক্ষেত্রেই সংশোধন করবে, তবে এটি আমার পরিবেশে স্থির হয়েছে। আমি কেবল ওয়েটফরএক্সিট ব্যবহার করছি না এবং আউটপুট এবং ত্রুটি সমাপ্তির সংকেত উভয়টিতেই ওয়েটহ্যান্ডল.ওয়েটএল ব্যবহার করছি। আমি খুশি হব, যদি কেউ এটির সাথে সম্ভাব্য সমস্যা দেখেন। বা যদি এটি কাউকে সাহায্য করবে। আমার জন্য এটি আরও ভাল কারণ সময়সীমা ব্যবহার করে না।

private static int DoProcess(string workingDir, string fileName, string arguments)
{
    int exitCode;
    using (var process = new Process
    {
        StartInfo =
        {
            WorkingDirectory = workingDir,
            WindowStyle = ProcessWindowStyle.Hidden,
            CreateNoWindow = true,
            UseShellExecute = false,
            FileName = fileName,
            Arguments = arguments,
            RedirectStandardError = true,
            RedirectStandardOutput = true
        },
        EnableRaisingEvents = true
    })
    {
        using (var outputWaitHandle = new AutoResetEvent(false))
        using (var errorWaitHandle = new AutoResetEvent(false))
        {
            process.OutputDataReceived += (sender, args) =>
            {
                // ReSharper disable once AccessToDisposedClosure
                if (args.Data != null) Debug.Log(args.Data);
                else outputWaitHandle.Set();
            };
            process.ErrorDataReceived += (sender, args) =>
            {
                // ReSharper disable once AccessToDisposedClosure
                if (args.Data != null) Debug.LogError(args.Data);
                else errorWaitHandle.Set();
            };

            process.Start();
            process.BeginOutputReadLine();
            process.BeginErrorReadLine();

            WaitHandle.WaitAll(new WaitHandle[] { outputWaitHandle, errorWaitHandle });

            exitCode = process.ExitCode;
        }
    }
    return exitCode;
}

আমি এটি ব্যবহার করেছি এবং টাইমআউট পরিচালনা করতে টাস্ক.আর দিয়ে আবৃত হয়েছি, আমি টাইম আউটকে হত্যার জন্য প্রসেসিডও ফিরিয়ে দিয়েছি
প্লাস

0

আমি মনে করি অ্যাসিঙ্কের সাথে, স্ট্যান্ডার্ড আউটপুট এবং স্ট্যান্ডার্ডএরর উভয় ব্যবহার করার পরেও আরও মার্জিত সমাধান এবং ডেডলক না থাকা সম্ভব:

using (Process process = new Process())
{
    process.StartInfo.FileName = filename;
    process.StartInfo.Arguments = arguments;
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.RedirectStandardError = true;

    process.Start();

    var tStandardOutput = process.StandardOutput.ReadToEndAsync();
    var tStandardError = process.StandardError.ReadToEndAsync();

    if (process.WaitForExit(timeout))
    {
        string output = await tStandardOutput;
        string errors = await tStandardError;

        // Process completed. Check process.ExitCode here.
    }
    else
    {
        // Timed out.
    }
}

এটি মার্ক বাইয়ার্স উত্তর উপর ভিত্তি করে। আপনি যদি অ্যাসিঙ্ক পদ্ধতিতে না হন তবে আপনি এর string output = tStandardOutput.result;পরিবর্তে ব্যবহার করতে পারেনawait


0

এই উত্তরগুলির মধ্যে আমার কোনওটিই সহায়তা করেনি, তবে এই সমাধানটি হ্যাংডিং হ্যান্ডলিংয়ের সাথে ভাল কাজ করেছে

https://stackoverflow.com/a/60355879/10522960


-1

এই পোস্টটি সম্ভবত পুরানো হতে পারে তবে আমি কেন এটি আটকে যায় তার মূল কারণটি রিডাইরেক্ট স্ট্যান্ডার্ডআউটপুট বা আপনার যদি রিডাইরেক্ট স্ট্যান্ডার্ডার্ডার থাকে তবে স্ট্যাক ওভারফ্লোর কারণে হয় out

আউটপুট ডেটা বা ত্রুটির ডেটা যেহেতু বড়, এটি স্থায়ী সময়ের কারণ হিসাবে এটি এখনও অনির্দিষ্ট সময়ের জন্য প্রক্রিয়াধীন রয়েছে।

সুতরাং এই সমস্যাটি সমাধান করতে:

p.StartInfo.RedirectStandardoutput = False
p.StartInfo.RedirectStandarderror = False

11
সমস্যাটি হ'ল লোকেরা স্পষ্টভাবে সেগুলিকে সত্য করে দেয় কারণ তারা সেই স্ট্রিমগুলিতে অ্যাক্সেস করতে সক্ষম হতে চায়! অন্যথায় আমরা তাদের মিথ্যা করতে পারি।
ব্যবহারকারী 276648

-1

আসুন আমরা এখানে পোস্ট করা নমুনা কোডটিকে রিডাইরেক্টর এবং অন্যান্য প্রোগ্রামটিকে পুনঃনির্দেশিত কল করতে পারি। যদি এটি আমার হয় তবে আমি সম্ভবত একটি পরীক্ষা পুনর্নির্দেশিত প্রোগ্রাম লিখব যা সমস্যার নকল করতে ব্যবহার করা যেতে পারে।

তাই আমি. পরীক্ষার ডেটার জন্য আমি ECMA-334 C # ভাষা নির্দিষ্টকরণের পিডিএফ ব্যবহার করেছি; এটি প্রায় 5MB নীচে এটির গুরুত্বপূর্ণ অংশটি দেওয়া হল।

StreamReader stream = null;
try { stream = new StreamReader(Path); }
catch (Exception ex)
{
    Console.Error.WriteLine("Input open error: " + ex.Message);
    return;
}
Console.SetIn(stream);
int datasize = 0;
try
{
    string record = Console.ReadLine();
    while (record != null)
    {
        datasize += record.Length + 2;
        record = Console.ReadLine();
        Console.WriteLine(record);
    }
}
catch (Exception ex)
{
    Console.Error.WriteLine($"Error: {ex.Message}");
    return;
}

ডেটাসাইজ মানটি প্রকৃত ফাইল আকারের সাথে মেলে না তবে এটি কোনও বিষয় নয়। এটি কোনও পিডিএফ ফাইল সর্বদা লাইনগুলির শেষে সিআর এবং এলএফ উভয়ই ব্যবহার করে তবে এটি স্পষ্ট নয় for আপনি পরীক্ষা করতে অন্য যে কোনও বড় টেক্সট ফাইল ব্যবহার করতে পারেন।

এটি ব্যবহার করে যখন আমি প্রচুর পরিমাণে ডেটা লিখি তবে আমি যখন অল্প পরিমাণে লিখি তখন নমুনা পুনর্নির্দেশক কোডটি স্তব্ধ হয়ে যায়।

আমি কোনওভাবে সেই কোডটির প্রয়োগের সন্ধান করার জন্য খুব চেষ্টা করেছি এবং আমি তা করতে পারি নি। আমি পুনঃনির্দেশিত প্রোগ্রামটির লাইনগুলি মন্তব্য করেছি যা পুনঃনির্দেশিত প্রোগ্রামের জন্য একটি পৃথক কনসোল উইন্ডো পাওয়ার চেষ্টা করার জন্য একটি কনসোল তৈরি নিষ্ক্রিয় করেছে তবে আমি তা করতে পারি নি।

তারপরে আমি একটি নতুন উইন্ডো, পিতামাতার উইন্ডো বা কোনও উইন্ডোতে কনসোল অ্যাপ্লিকেশনটি কীভাবে শুরু করব তা খুঁজে পেয়েছি । সুতরাং স্পষ্টতই আমরা (সহজেই) পৃথক কনসোল রাখতে পারি না যখন একটি কনসোল প্রোগ্রাম শেলএক্সেকিউট ছাড়াই অন্য একটি কনসোল প্রোগ্রাম শুরু করে এবং যেহেতু শেলএকসেকিউট পুনর্নির্দেশ সমর্থন করে না আমরা অবশ্যই একটি কনসোল ভাগ করে নেব, এমনকি যদি আমরা অন্য প্রক্রিয়াটির জন্য কোনও উইন্ডো নির্দিষ্ট না করি।

আমি ধরে নিয়েছি যে যদি পুনঃনির্দেশিত প্রোগ্রামটি কোথাও কোনও বাফার পূরণ করে তবে ডেটা পড়ার জন্য এটি অবশ্যই অপেক্ষা করতে হবে এবং যদি সেই সময়ে কোনও তথ্য পুনর্নির্দেশক দ্বারা না পড়ে থাকে তবে এটি একটি অচলাবস্থা।

সমাধানটি হ'ল ReadToEnd ব্যবহার না করা এবং ডেটা লেখার সময় ডেটা পড়ার জন্য তবে অ্যাসিঙ্ক্রোনাস রিড ব্যবহার করা প্রয়োজন হয় না। সমাধানটি বেশ সহজ হতে পারে। নিম্নলিখিতটি আমার জন্য 5 এমবি পিডিএফ নিয়ে কাজ করে।

ProcessStartInfo info = new ProcessStartInfo(TheProgram);
info.CreateNoWindow = true;
info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
Process p = Process.Start(info);
string record = p.StandardOutput.ReadLine();
while (record != null)
{
    Console.WriteLine(record);
    record = p.StandardOutput.ReadLine();
}
p.WaitForExit();

আর একটি সম্ভাবনা হ'ল পুনঃনির্দেশটি করার জন্য একটি জিইউআই প্রোগ্রাম ব্যবহার করা। পূর্ববর্তী কোডটি ডাব্লুপিএফ অ্যাপ্লিকেশনটিতে সুস্পষ্ট পরিবর্তন ছাড়া কাজ করে।


-3

আমি একই সমস্যা ছিল, কিন্তু কারণ ছিল ভিন্ন। এটি তবে উইন্ডোজ 8 এর অধীনে ঘটবে, তবে উইন্ডোজ under এর অধীনে নয়, নিম্নলিখিত লাইনটি সমস্যার কারণ বলে মনে হচ্ছে।

pProcess.StartInfo.UseShellExecute = False

সমাধানটি ছিল ইউজশেলএক্সেকুট অক্ষম না করা। আমি এখন একটি শেল পপআপ উইন্ডো পেয়েছি, যা অযাচিত, তবে প্রোগ্রামটির থেকে অনেক ভাল হওয়ার জন্য অপেক্ষা করছে। সুতরাং আমি তার জন্য নিম্নলিখিত কাজগুলি জুড়েছি:

pProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden

এখন আমাকে বিরক্ত করার একমাত্র বিষয় হ'ল এটি কেন প্রথম স্থানে উইন্ডোজ 8 এর অধীনে হচ্ছে।


1
আপনি UseShellExecuteযদি আউটপুট পুনর্নির্দেশ করতে চান তবে আপনাকে মিথ্যাতে সেট করতে হবে।
ব্র্যাড মুর
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.