C# 如何使该方法首先返回一个字符串,然后继续代码的其余部分?
我有一个web服务器,我添加了以下方法:C# 如何使该方法首先返回一个字符串,然后继续代码的其余部分?,c#,.net,winforms,C#,.net,Winforms,我有一个web服务器,我添加了以下方法: public async Task<string> SendResponseAsync(HttpListenerRequest request)//public string SendResponse(HttpListenerRequest request) { string result = ""; string key = request.QueryString.GetKey
public async Task<string> SendResponseAsync(HttpListenerRequest request)//public string SendResponse(HttpListenerRequest request)
{
string result = "";
string key = request.QueryString.GetKey(0);
if (key == "cmd")
{
if (request.QueryString[0] == "uploadstatus")
{
switch (Youtube_Uploader.uploadstatus)
{
case "uploading file":
return "uploading " + Youtube_Uploader.fileuploadpercentages;
case "status":
return Youtube_Uploader.fileuploadpercentages.ToString();
case "file uploaded successfully":
Youtube_Uploader.uploadstatus = "";
Youtube_Uploader.fileuploadpercentages + ","
+ Youtube_Uploader.time;
default:
return "upload unknown state";
}
}
if (request.QueryString[0] == "nothing")
{
return "Connection Success";
}
if (request.QueryString[0] == "start")
{
StartRecrod();
result = "Recording started";
}
if (request.QueryString[0] == "stop")
{
dirchanged = false;
StartRecrod();
result = "Recording stopped and preparing the file to be shared on youtube";
string fileforupload = await WatchDirectory();
await WaitForUnlockedFile(fileforupload);
uploadedFilesList.Add(fileforupload);
Youtube_Uploader youtubeupload = new Youtube_Uploader(fileforupload);//uploadedFilesList[0]);
}
}
else
{
result = "Nothing have been done";
}
return result;
}
问题是,在完成等待之前,它不会返回结果。
但我需要让它先返回结果,然后再返回其他结果
这是WatchDirectory方法:
private async Task<string> WatchDirectory()
{
using (FileSystemWatcher watcher = new FileSystemWatcher())
{
TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
watcher.Path = userVideosDirectory;
watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size;
watcher.Filter = "*.mp4";
watcher.Changed += (sender, e) => tcs.SetResult(e.FullPath);
watcher.EnableRaisingEvents = true;
return await tcs.Task;
}
}
更新:
这就是我在form1构造函数中创建Web服务器实例并使用SendResponseAsync方法的方式
var ws = new WebServer(
request => Task.Run(() => SendResponseAsync(request)),
"http://+:8098/");
这是WebServer类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Threading;
namespace Automatic_Record
{
class WebServer
{
private readonly HttpListener _listener = new HttpListener();
private readonly Func<HttpListenerRequest, Task<string>> _responderMethod;
public WebServer(string[] prefixes, Func<HttpListenerRequest, Task<string>> method)
{
if (!HttpListener.IsSupported)
throw new NotSupportedException(
"Needs Windows XP SP2, Server 2003 or later.");
// URI prefixes are required, for example
// "http://localhost:8080/index/".
if (prefixes == null || prefixes.Length == 0)
throw new ArgumentException("prefixes");
// A responder method is required
if (method == null)
throw new ArgumentException("method");
foreach (string s in prefixes)
_listener.Prefixes.Add(s);
_responderMethod = method;
_listener.Start();
}
public WebServer(Func<HttpListenerRequest, Task<string>> method, params string[] prefixes)
: this(prefixes, method) { }
public void Run()
{
ThreadPool.QueueUserWorkItem((o) =>
{
Console.WriteLine("Webserver running...");
try
{
while (_listener.IsListening)
{
ThreadPool.QueueUserWorkItem(async (c) =>
{
var ctx = c as HttpListenerContext;
try
{
string rstr = await _responderMethod(ctx.Request);
System.Diagnostics.Trace.Write(ctx.Request.QueryString);
//ctx.Request.QueryString
byte[] buf = Encoding.UTF8.GetBytes(rstr);
ctx.Response.ContentLength64 = buf.Length;
ctx.Response.OutputStream.Write(buf, 0, buf.Length);
System.Data.SqlClient.SqlConnectionStringBuilder builder = new System.Data.SqlClient.SqlConnectionStringBuilder();
}
catch (Exception error)
{
string ttt = error.ToString();
} // suppress any exceptions
finally
{
// always close the stream
ctx.Response.OutputStream.Close();
}
}, _listener.GetContext());
}
}
catch { } // suppress any exceptions
});
}
public void Stop()
{
_listener.Stop();
_listener.Close();
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
Net系统;
使用系统线程;
名称空间自动记录
{
类Web服务器
{
私有只读HttpListener _listener=new HttpListener();
私有只读函数响应方法;
公共Web服务器(字符串[]前缀,Func方法)
{
如果(!HttpListener.IsSupported)
抛出新的NotSupportedException(
“需要Windows XP SP2、Server 2003或更高版本。”);
//例如,URI前缀是必需的
// "http://localhost:8080/index/".
if(前缀==null | |前缀.长度==0)
抛出新的ArgumentException(“前缀”);
//需要响应者方法
if(方法==null)
抛出新的ArgumentException(“方法”);
foreach(前缀中的字符串s)
_listener.Prefixes.Add(s);
_responderMethod=方法;
_listener.Start();
}
公共Web服务器(Func方法,参数字符串[]前缀)
:this(前缀、方法){}
公开募捐
{
ThreadPool.QueueUserWorkItem((o)=>
{
WriteLine(“正在运行的Web服务器…”);
尝试
{
while(_listener.IsListening)
{
ThreadPool.QueueUserWorkItem(异步(c)=>
{
var ctx=c作为HttpListenerContext;
尝试
{
字符串rstr=wait_responderMethod(ctx.Request);
系统.诊断.跟踪.写入(ctx.请求.查询字符串);
//ctx.Request.QueryString
字节[]buf=Encoding.UTF8.GetBytes(rstr);
ctx.Response.ContentLength64=基本长度;
ctx.Response.OutputStream.Write(buf,0,buf.Length);
System.Data.SqlClient.SqlConnectionStringBuilder builder=new System.Data.SqlClient.SqlConnectionStringBuilder();
}
捕获(异常错误)
{
字符串ttt=error.ToString();
}//禁止任何异常
最后
{
//始终关闭小溪
ctx.Response.OutputStream.Close();
}
},_listener.GetContext());
}
}
catch{}//禁止任何异常
});
}
公共停车场()
{
_listener.Stop();
_listener.Close();
}
}
如果我理解正确,在SendResponseAsync()
方法的操作过程中,您有多个“检查点”,并且在每个检查点上,您都希望能够向客户端发送带有某些状态消息的响应(例如,您希望报告结果“录制已停止,并准备在youtube上共享文件”
在调用WatchDirectory()
完成之后,但在执行调用WaitForUnlockedFile()
之前
基本问题是SendResponseAsync()
方法可以像任何其他方法async
或其他方法一样,只返回一个值。任何方法都不能返回一次以上†,对于async
方法和任何其他类型的方法一样
那么,该怎么办呢?好吧,如果不在上下文中查看代码(即,如果没有可靠地再现您的问题),就不可能确定。但是C#中的一种惯用方法是使用IProgress
接口,允许用状态值回调方法的调用方,以便它能够适当地处理它们(例如,发送给客户)
例如,您可以将方法更改为如下所示:
public async Task SendResponseAsync(
HttpListenerRequest request, IProgress<string> progress)
{
string key = request.QueryString.GetKey(0);
if (key == "cmd")
{
if (request.QueryString[0] == "uploadstatus")
{
switch (Youtube_Uploader.uploadstatus)
{
case "uploading file":
progress.Report("uploading " + Youtube_Uploader.fileuploadpercentages);
return;
case "status":
progress.Report(Youtube_Uploader.fileuploadpercentages.ToString());
return;
case "file uploaded successfully":
Youtube_Uploader.uploadstatus = "";
Youtube_Uploader.fileuploadpercentages + ","
+ Youtube_Uploader.time;
default:
progress.Report("upload unknown state");
return;
}
}
if (request.QueryString[0] == "nothing")
{
progress.Report("Connection Success");
return;
}
if (request.QueryString[0] == "start")
{
StartRecrod();
progress.Report("Recording started");
}
if (request.QueryString[0] == "stop")
{
dirchanged = false;
StartRecrod();
string fileforupload = await WatchDirectory();
progress.Report("Recording stopped and preparing the file to be shared on youtube");
await WaitForUnlockedFile(fileforupload);
uploadedFilesList.Add(fileforupload);
Youtube_Uploader youtubeupload = new Youtube_Uploader(fileforupload);//uploadedFilesList[0]);
}
}
else
{
progress.Report("Nothing have been done");
}
}
string result = await SendResponseAsync(request);
SendResultToClient(result);
await SendResponseAsync(request, new Progress<string>(s => SendResultToClient(s)));
var ws = new WebServer(SendResponseAsync, "http://+:8098/");
然后您可以调用该方法的新版本,如下所示:
public async Task SendResponseAsync(
HttpListenerRequest request, IProgress<string> progress)
{
string key = request.QueryString.GetKey(0);
if (key == "cmd")
{
if (request.QueryString[0] == "uploadstatus")
{
switch (Youtube_Uploader.uploadstatus)
{
case "uploading file":
progress.Report("uploading " + Youtube_Uploader.fileuploadpercentages);
return;
case "status":
progress.Report(Youtube_Uploader.fileuploadpercentages.ToString());
return;
case "file uploaded successfully":
Youtube_Uploader.uploadstatus = "";
Youtube_Uploader.fileuploadpercentages + ","
+ Youtube_Uploader.time;
default:
progress.Report("upload unknown state");
return;
}
}
if (request.QueryString[0] == "nothing")
{
progress.Report("Connection Success");
return;
}
if (request.QueryString[0] == "start")
{
StartRecrod();
progress.Report("Recording started");
}
if (request.QueryString[0] == "stop")
{
dirchanged = false;
StartRecrod();
string fileforupload = await WatchDirectory();
progress.Report("Recording stopped and preparing the file to be shared on youtube");
await WaitForUnlockedFile(fileforupload);
uploadedFilesList.Add(fileforupload);
Youtube_Uploader youtubeupload = new Youtube_Uploader(fileforupload);//uploadedFilesList[0]);
}
}
else
{
progress.Report("Nothing have been done");
}
}
string result = await SendResponseAsync(request);
SendResultToClient(result);
await SendResponseAsync(request, new Progress<string>(s => SendResultToClient(s)));
var ws = new WebServer(SendResponseAsync, "http://+:8098/");
那么构造函数调用应该如下所示:
public async Task SendResponseAsync(
HttpListenerRequest request, IProgress<string> progress)
{
string key = request.QueryString.GetKey(0);
if (key == "cmd")
{
if (request.QueryString[0] == "uploadstatus")
{
switch (Youtube_Uploader.uploadstatus)
{
case "uploading file":
progress.Report("uploading " + Youtube_Uploader.fileuploadpercentages);
return;
case "status":
progress.Report(Youtube_Uploader.fileuploadpercentages.ToString());
return;
case "file uploaded successfully":
Youtube_Uploader.uploadstatus = "";
Youtube_Uploader.fileuploadpercentages + ","
+ Youtube_Uploader.time;
default:
progress.Report("upload unknown state");
return;
}
}
if (request.QueryString[0] == "nothing")
{
progress.Report("Connection Success");
return;
}
if (request.QueryString[0] == "start")
{
StartRecrod();
progress.Report("Recording started");
}
if (request.QueryString[0] == "stop")
{
dirchanged = false;
StartRecrod();
string fileforupload = await WatchDirectory();
progress.Report("Recording stopped and preparing the file to be shared on youtube");
await WaitForUnlockedFile(fileforupload);
uploadedFilesList.Add(fileforupload);
Youtube_Uploader youtubeupload = new Youtube_Uploader(fileforupload);//uploadedFilesList[0]);
}
}
else
{
progress.Report("Nothing have been done");
}
}
string result = await SendResponseAsync(request);
SendResultToClient(result);
await SendResponseAsync(request, new Progress<string>(s => SendResultToClient(s)));
var ws = new WebServer(SendResponseAsync, "http://+:8098/");
当然,您已经修改了SendResponseAsync()
,正如我上面解释的那样,这样它就可以接收IProgress
的实例作为参数
完成所有这些之后,您的WebServer
类的Run()中的代码块
将结果文本写入响应输出流的方法封装在一个匿名方法中,该方法用作传递给\u responseMethod
委托调用的进度
实例的委托
注意:
上述内容在您的场景中可能是正确的,也可能是不正确的。同样,如果没有一个好的代码示例,也不可能确定。但是请记住,进度
类在创建时使用当前的同步上下文
来引发其进度更改
事件。在许多情况下,这正是您想要的。但根据此处调用的上下文,这是可能的