Я пытаюсь собрать выходные данные в реальном времени из общедоступной асинхронной задачи RunProcessAsync() и отправить в Form1 через синхронизациюContext.Post() и progress.Report() для обработки там, для целей отладки метки времени добавляются как в выходные данные, так и в полученные данные. код RunProcessAsync() изменен с https://gist.github.com/NSouth/6d44d07db97df7d41bce33ac3117fdeb.
Полученные данные сохраняются в Form1 и выводятся с помощью btnShow()
Обнаружено, что progress.Report() отправляет данные одновременно с stdOutBuilder.Append(), но synchronizeContext.Post() отправляет после RunProcessAsync(). Оба данных поступают в Form1 после завершения RunProcessAsync().
Я пытаюсь добавить System.Windows.Forms.Application.DoEvents();, но никаких улучшений.
These are the data collected with timestamp
processStartInfo.FileName = @"C:\WINDOWS\system32\cmd.exe";
processStartInfo.Arguments = @"/k Dir C:\ /on ";
stdOutBuilder.Append()
08:05.407 16/07/2020 22:58 <DIR> AndroidStudio
08:05.407 28/06/2020 21:03 <DIR> App
08:05.408 21/06/2017 20:50 <DIR> MP_Upload
VS2013 debug Output
08:05.407 16/07/2020 22:58 <DIR> AndroidStudio
08:05.407 28/06/2020 21:03 <DIR> App
08:05.408 21/06/2017 20:50 <DIR> MP_Upload
m_SynchronizationContext.Post
08:05.452 08:05.452 16/07/2020 22:58 <DIR> AndroidStudio
08:05.453 08:05.453 28/06/2020 21:03 <DIR> App
08:05.453 08:05.453 21/06/2017 20:50 <DIR> MP_Upload
progress.Report
08:05.452 08:05.407 16/07/2020 22:58 <DIR> AndroidStudio
08:05.453 08:05.408 28/06/2020 21:03 <DIR> App
08:05.454 08:05.408 21/06/2017 20:50 <DIR> MP_Upload
^^^^^ ^^^^^------- timestamp same as stdOutBuilder.Append()
^^^^^------ arrive after RunProcessAsync() completed
Может ли кто-нибудь помочь мне, чтобы Form1 могла получать данные в режиме реального времени?
Ниже используется код:
public async Task<Result> RunProcessAsync(ProcessStartInfo startInfo, IProgress<ExecuteDosCmd.Form1.ProgressObject> progress, string stdIn = null, int? timeoutMs = null)
// modify from https://gist.github.com/NSouth/6d44d07db97df7d41bce33ac3117fdeb
{
......
process.OutputDataReceived += (s, e) =>
{
if (e.Data == null)
{
stdOutCloseEvent.TrySetResult(true);
}
else
{
stdOutBuilder.Append(DateTime.Now.ToString("mm:ss.fff ") + e.Data +"\n");
//08:05.407 16/07/2020 22:58 <DIR> AndroidStudio
//08:05.407 28/06/2020 21:03 <DIR> App
//08:05.408 21/06/2017 20:50 <DIR> MP_Upload
debugPr(e.Data);
//08:05.407 16/07/2020 22:58 <DIR> AndroidStudio
//08:05.407 28/06/2020 21:03 <DIR> App
//08:05.408 21/06/2017 20:50 <DIR> MP_Upload
m_SynchronizationContext.Post(_ => ExecuteDosCmd.Form1.form1.updateProgress01(DateTime.Now.ToString("mm:ss.fff ") + e.Data + "\n"), null);
//08:05.452 08:05.452 16/07/2020 22:58 <DIR> AndroidStudio
//08:05.453 08:05.453 28/06/2020 21:03 <DIR> App
//08:05.453 08:05.453 21/06/2017 20:50 <DIR> MP_Upload
//System.Windows.Forms.Application.DoEvents();
progress.Report(new ExecuteDosCmd.Form1.ProgressObject() { Percentage = 20, Message = DateTime.Now.ToString("mm:ss.fff ") + e.Data + "\n" });
//08:05.452 08:05.407 16/07/2020 22:58 <DIR> AndroidStudio
//08:05.453 08:05.408 28/06/2020 21:03 <DIR> App
//08:05.454 08:05.408 21/06/2017 20:50 <DIR> MP_Upload
^^^^^ ^^^^^------- timestamp same as stdOutBuilder.Append()
^^^^^------ arrive after RunProcessAsync() completed
//System.Windows.Forms.Application.DoEvents();
}
};
processTasks.Add(stdOutCloseEvent.Task);
......
}
// Form1
public class ProgressObject
{
public int Percentage { get; set; }
public string Message { get; set; }
}
string str2 = "";
private void updateProgress02(ProgressObject prog)
{
//debugPr(prog.Message);
str2 += (DateTime.Now.ToString("mm:ss.fff ") + prog.Message);
rtbError.AppendText(DateTime.Now.ToString("mm:ss.fff ") + prog.Message);
}
private void debugPr(String s)
{
System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString("mm:ss.fff ") + s); // Output will be in Visual Studio debug window or Dbgview.exe
}
string str = "";
public void updateProgress01(string msg)
{
str += (DateTime.Now.ToString("mm:ss.fff ") + msg );
progressBar1.Value = progressBar1.Value + 1;
debugPr(""+progressBar1.Value);
}
private void btnShow_Click(object sender, EventArgs e)
{
rtbOutput.AppendText("\n\n"+DateTime.Now.ToString("mm:ss.fff ") + "\n\nm_SynchronizationContext.Post\n");
rtbOutput.AppendText(str);
rtbOutput.AppendText("\n\nprogress.Report\n");
rtbOutput.AppendText(str2);
}
private void btnStart_Click(object sender, EventArgs e)
{
debugPr("ProcessAsyncHelper03");
ProcessAsyncHelper03 ph = new ProcessAsyncHelper03();
Task<ExecuteDosCmd.ProcessAsyncHelper03.Result> task3 = ph.RunProcessAsync(psi, new Progress<ProgressObject>(updateProgress02), null, 2000);
rtbOutput.Text = task3.Result.StdOut;
rtbError.AppendText(task3.Result.StdErr);
rtbError.AppendText("\nExitCode: " + task3.Result.ExitCode +"\n\n");
}
rtbOutput.Text = task3.Result.StdOut;
. Почему вы смешиваете SynchronizationContext и Progress‹T›? Это для теста? См. несколько простых примеров здесь. - person Jimi   schedule 18.07.2020btnStart_Click
)async
. Или запустить задачу. - person Jimi   schedule 18.07.2020Result
). Измените свою задачу на общедоступнуюasync Task RunProcessAsync(int processId, IProgress<ProgressObject> progress) { }
, используйте только объектPrograss<T>
для отчета о ходе выполнения (вы не используете другие параметры, передайтеProcess.Id
, чтобы указать процесс, который вы хотите протестировать, или его имя, в зависимости от того, как вы хотите его обработать). - person Jimi   schedule 19.07.2020btnStart_Click
async
иawait RunProcessAsync()
, передав объектProgress<ProgressObject>
, который вы создали заранее. - person Jimi   schedule 19.07.2020