我已经使用c#.net构建了GUI,如果在单击“继续”按钮时在面板上选择复选框,则需要合并一个python脚本。 Python脚本应在后台运行,然后我想将字符串结果打印在GUI启动的主过程末尾的消息框中。重要的是,如果选择了复选框,我只希望弹出消息框。
我了解如何从C#调用Python,但是对于如何使用异步函数收集和显示结果,我仍然有些模糊。我根据Microsoft文档了解我需要使用任务对象,但是我无法完全按照自己的意图运行。这是我到目前为止在代码中使用的文档以供参考: https://learn.microsoft.com/en-us/dotnet/csharp/csharp/programming-guide/concepts/async/
这是我第一次在C#中使用async。
这是我的相关功能的代码(为了清晰缩短),然后我将详细描述问题:
async private void proceedClicked()
{
if (checkBox.Checked)
{
string cmd = ""; // some python command
Task<string> pythonTask = runProcAsync(cmd);
}
// do some other processing
if (checkBox.Checked)
{
var pythonResult = await pythonTask;
// print result to a message box
}
}
private Task runProcAsync(string cmd)
{
return Task.Run(() =>
{
callPython(cmd);
});
}
private string callPython(string cmd)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "python.exe";// full path to python
start.Arguments = cmd;
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
return result;
}
}
}
以下是我的问题,详细介绍了我的实现方法:
- 我如何使任务和任务对象对齐匹配?我尝试使用任务,然后尝试使用task.result()获取字符串,但是Result()不存在作为我声明的任务VAR的方法。然后,我尝试使用任务&lt;&gt;作为类型,但是task.run()抱怨不支持的隐式转换,必须是明确的。 (字符串应该在我的第二种方法中,但是格式阻止了我和IDK如何修复它)。
- 如何声明任务对象,以便在两个条件范围中出现?我尝试用外部范围内的构造函数声明它,并且对象没有构造函数。我能够在没有构造函数的情况下声明外部范围中的变量,但是随后我在第二个范围中遇到了一个错误,即该变量在第一个范围内分配后未分配。我的直觉告诉我在外部范围内将其声明为无,在第一个条件块中分配,然后在第二条条件块中检查一个值以外的值。
- 我对异步/等待适当/正确的使用,还是有贝特的方式?由于我打电话给一个过程,这将如何影响异步的使用?
事先感谢您的建议/帮助!
I have built a GUI using C# .NET and I need to incorporate a Python script to be called if a checkbox is selected on the panel when the "PROCEED" button is clicked. The python script should run in the background and then I'd like to print the string result in a message box at the end of the main process launched by the GUI. The important thing is that I only want the message box to pop up if the checkbox was selected.
I understand how I can call Python from C#, but I am still a bit fuzzy on how I can collect and display the result using an async function. I understand based on Microsoft docs that I need to use the Task object, but I cannot quite get this to function the way I am intending. Here are the docs I used in my code so far for reference: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/
This is my first time using async in C#.
Here is my code for the relevant functions(shortened for clarity), and then I will describe the issues in detail with questions:
async private void proceedClicked()
{
if (checkBox.Checked)
{
string cmd = ""; // some python command
Task<string> pythonTask = runProcAsync(cmd);
}
// do some other processing
if (checkBox.Checked)
{
var pythonResult = await pythonTask;
// print result to a message box
}
}
private Task runProcAsync(string cmd)
{
return Task.Run(() =>
{
callPython(cmd);
});
}
private string callPython(string cmd)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "python.exe";// full path to python
start.Arguments = cmd;
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
return result;
}
}
}
Here are my issues with some details about my implementation approaches:
- How do I align the Task and Task objects so that they match? I have tried using Task and then Task.Result() to get the string, but Result() doesn't exist as a method for the Task var I declared. Then I have tried using Task<> as the type, but Task.Run() complains about the implicit conversion as it is not supported and must be explicit. (string should be in those carats for my second approach, but the formatting is preventing me and IDK how to fix it).
- How can I declare the Task object so it appears in both conditional scopes? I tried declaring it with a constructor in the outer scope and there is no constructor for the object. I am able to declare the variable in the outer scope without a constructor, but then I get an error in the second scope that the variable is unassigned after assignment in the first scope. My intuition tells me to declare it in the outer scope as none, assign in the first conditional block, and then check for a value other than none in the second conditional block.
- Is my use of async/await appropriate/correct, or is there a bette way? Since I am calling a process, how would this affect the use of async?
Thanks in advance for the advice/assistance!
发布评论
评论(2)
除了返回结果的问题外,您不应在异步代码中使用阻止功能。而是一直使用异步:
Apart from the issue around returning the result, you should not use blocking functions in async code. Instead use async all the way:
可能应该是:
随时在
任务
s s 在这里及其指南基于任务的异步编程。我注意到您还在尝试使用
task.task.result
就像是一种方法一样,实际上它是任务类。
Should probably be:
Feel free to review some of Microsoft's documentation on
Task
s here and here, and their guide to Task-based asynchronous programming.I noticed you are also trying to use
Task.Result
as if it were a method, when in fact it is a property of theTask
class.