private async Task <Testcase> GetTestcaseAsync(int i, int serial) { Testcase testcase = new Testcase(); if (isSample) { testcase.Serial = samples[i].Serial; testcase.ProblemId = samples[i].ProblemId; testcase.In = samples[i].In; testcase.Out = samples[i].Out; } else { testcase = await HttpClientManager.ExecuteGetJsonAsync <Testcase>(string.Format(FIND_BY_PROBLEM_ID_TESTCASE, probrem.id, serial)); if (testcase.In.Contains("(terminated because of the limitation)")) { testcase.In = await HttpClientManager.ExecuteGetStringAsync(string.Format(FIND_BY_PROBLEM_ID_TESTCASE_ALT_IN, probrem.id, serial)); } if (testcase.Out.Contains("(terminated because of the limitation)")) { testcase.Out = await HttpClientManager.ExecuteGetStringAsync(string.Format(FIND_BY_PROBLEM_ID_TESTCASE_ALT_OUT, probrem.id, serial)); } } return(testcase); }
private Result ExecTest(ProcessStartInfo startInfo, Testcase testcase) { var result = new Result(); var timeout = TimeSpan.FromSeconds(probrem.problemtimelimit * 4); bool isTimedOut = false; bool isMemoryExceeded = false; bool isError = false; long memory = 0; TimeSpan time = new TimeSpan(); var stdout = new StringBuilder(); var stderr = new StringBuilder(); string text = testcase.In.Replace("\n", "\r\n"); //string[] text = testcase.In.Replace("\n", "\r\n").Split(new string[] { "\r\n" }, StringSplitOptions.None); using (Process process = Process.Start(startInfo)) { process.OutputDataReceived += (ss, ee) => { if (ee.Data != null) { stdout.AppendLine(ee.Data); } }; // 標準出力に書き込まれた文字列を取り出す process.ErrorDataReceived += (ss, ee) => { if (ee.Data != null) { stderr.AppendLine(ee.Data); } }; // 標準エラー出力に書き込まれた文字列を取り出す process.BeginOutputReadLine(); process.BeginErrorReadLine(); //process.StandardInput.WriteLine(text); タイムアウトする処理の場合、受け側で読み込みが開始せず遅延するため、非同期処理に変更 process.StandardInput.WriteLineAsync(text); DateTime startTime = DateTime.Now; do //プロセスが終了するまで監視 { try { process.Refresh(); time = DateTime.Now - startTime; memory = Math.Max(memory, process.PeakWorkingSet64); } catch (InvalidOperationException) { } //プロセスが終了している場合、何もしない catch (ArgumentException) { } //プロセスが開かれていない場合も、何もしない if (!string.IsNullOrEmpty(stderr.ToString())) { isError = true; process.WaitForExit(); } if (memory > probrem.problemmemorylimit * 1024) { isMemoryExceeded = true; } if (time.TotalMilliseconds > timeout.TotalMilliseconds) { isTimedOut = true; } if (isMemoryExceeded || isTimedOut) { try { process.Kill(); process.WaitForExit(); } catch (Win32Exception) { } //プロセスが終了中の場合、何もしない catch (InvalidOperationException) { } //プロセスが終了している場合、何もしない } } while (!process.HasExited); process.WaitForExit(); process.CancelOutputRead(); process.CancelErrorRead(); result.ProcessingTime = time; result.UsedMemory = memory; } var resultString = stdout.ToString(); result.Output = resultString; string res; if (isMemoryExceeded || isTimedOut) { if (isMemoryExceeded) { res = "MLE"; } else { res = "TLE"; } } else { if (isError) { res = "RE"; txtError.Text = stderr.ToString(); } else { if (resultString == testcase.Out.Replace("\n", "\r\n"))//改行の統一 { res = "AC"; } else { res = "WA"; } } } result.Status = res; return(result); }