private async Task Judge(CompileResult res1, CompileResult res2, Encoding languageEncoding) { int peakRunTimeMs = 0; float peakMemoryMb = 0; var info = new Process2JudgeInfo { MemoryLimitMb = _fullM.MemoryLimitMb, TimeLimitMs = _fullM.TimeLimitMs, Path1 = res1.PathToAssembly, Path2 = res2.PathToAssembly }; for (short times = 0; times < _fullM.RunTimes; ++times) { _log.DebugExt($"NativeDll Juding {times + 1} of {_fullM.RunTimes}..."); Process2JudgeResult result = Sandbox.Process2Judge(info, languageEncoding); _log.DebugExt("NativeDll Judged."); peakRunTimeMs = Math.Max(peakRunTimeMs, result.TimeMs); peakMemoryMb = Math.Max(peakMemoryMb, result.MemoryMb); if (!result.Process1Ok) { await _client.Update(ClientJudgeModel.Create(_spush.Id, SolutionState.RuntimeError, peakRunTimeMs, peakMemoryMb)); return; } if (!result.Process2Ok) { await _client.Update(ClientJudgeModel.Create(_spush.Id, SolutionState.RuntimeError, peakRunTimeMs, peakMemoryMb)); return; } if (!result.Accepted) { await _client.Update(ClientJudgeModel.CreateProcess2WrongAnswer(_spush.Id, peakRunTimeMs, peakMemoryMb, result.P1Result.Output, result.P2Result.Output)); return; } } await _client.Update(ClientJudgeModel.Create(_spush.Id, SolutionState.Accepted, peakRunTimeMs, peakMemoryMb)); }
public static Process2JudgeResult Process2Judge(Process2JudgeInfo p2info, Encoding languageEncoding) { // 步骤: // 1、启动评测 // 2、将进程输入、输出重定向 // 3、等待程序运行完成 // 4、处理并返回程序运行结果。 // 1、启动评测 var info1 = new SandboxRunInfo { LimitProcessCount = 1, MemoryLimitMb = 512.0f, TimeLimitMs = 10000, Path = p2info.Path1 }; SandboxIoResult io1 = BeginRun(info1); if (!io1.Succeed) { EndRun(io1.InstanceHandle); return(new Process2JudgeResult { P1Result = (JudgeResult)io1 }); } var info2 = new SandboxRunInfo { LimitProcessCount = 1, MemoryLimitMb = p2info.MemoryLimitMb, TimeLimitMs = p2info.TimeLimitMs, Path = p2info.Path2 }; SandboxIoResult io2 = BeginRun(info2); if (!io2.Succeed) { EndRun(io2.InstanceHandle); return(new Process2JudgeResult { P2Result = (JudgeResult)io2 }); } // 2、将两个进程的输入输出重定向。 Func <FileStream, FileStream, CancellationToken, Task> transformFunc = async(toRead, toWrite, cancel) => { var buffer = new char[4096]; using (var reader = new StreamReader(toRead, Encoding.Default)) using (var writer = new StreamWriter(toWrite)) { while (!cancel.IsCancellationRequested) { var c = await reader.ReadAsync(buffer, 0, buffer.Length); if (c != 0) { await writer.WriteAsync(buffer, 0, c); Debug.WriteLine($"{Task.CurrentId}: {new string(buffer, 0, c)}"); await writer.FlushAsync(); } else { await Task.Delay(10); } } } }; var cancelToken = new CancellationTokenSource(); var transform12 = transformFunc(io1.OutputReadStream, io2.InputWriteStream, cancelToken.Token); var transform21 = transformFunc(io2.OutputReadStream, io1.InputWriteStream, cancelToken.Token); var stdErrorTask = ReadToEndFrom(io1.ErrorReadStream, languageEncoding); io2.ErrorReadStream.Dispose(); // 3、等待程序运行完成 var run1 = EndRun(io1.InstanceHandle); var run2 = EndRun(io2.InstanceHandle); cancelToken.Cancel(throwOnFirstException: false); transform21.Wait(); transform12.Wait(); stdErrorTask.Wait(); // 4、返回运行结果。 var toReturn = new Process2JudgeResult { P1Result = (JudgeResult)run1, P2Result = (JudgeResult)run2 }; toReturn.P1Result.Output = stdErrorTask.Result; return(toReturn); }