【发布时间】:2015-11-15 08:37:36
【问题描述】:
我有一个网络服务器,我添加了这个方法:
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;
}
问题出在这部分:
result = "Recording stopped and preparing the file to be shared on youtube";
string fileforupload = await WatchDirectory();
await WaitForUnlockedFile(fileforupload);
问题是它不会返回结果,直到它完成等待。 但我需要以某种方式使其首先返回结果,然后再返回结果。
这是 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;
}
}
还有WaitForUnlockedFile方法:
private async Task WaitForUnlockedFile(string fileName)
{
while (true)
{
try
{
using (IDisposable stream = File.Open(fileName, FileMode.OpenOrCreate,
FileAccess.ReadWrite, FileShare.None))
{ /* on success, immediately dispose object */ }
break;
}
catch (IOException)
{
}
await Task.Delay(100);
}
}
更新:
这就是我在 form1 构造函数中为 WebServer 创建实例并使用方法 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.Threading.Thread.Sleep(5000);' ?
-
完全不清楚您要在这里做什么 -
WatchDirectory和WaitForUnlockedFile做什么?您希望如何在方法完成之前使用它的结果?您需要更彻底地解释这一点。 -
蚂蚁我会解释。这个方法是我在 c# 上的 web 服务器的一部分,我正在使用这个方法从我的 java 程序客户端获取命令。客户端每秒发送一次命令,我在方法中检查它并根据情况向客户端返回一个字符串。在这种情况下,“停止”就像在“开始”等其他情况下一样,我在 java 端向客户端返回一个字符串,在 java 端我使用 texttospeech 来说出字符串。在这种情况下,它应该说:录制停止并准备要在 youtube 上共享的文件问题是 AWAIT 行使其保持不变并且仅在等待之后。
-
只有在等待完成后,它才会发送字符串“录制停止并准备要在 youtube 上共享的文件”。问题是这个等待需要一些时间。这可能需要一秒钟,有时甚至需要 30 秒或更长时间。等待做什么?在 WatchDirectory 和 WaitForUblockedFile 中,我正在等待写入文件。有时文件可能是 1kb,有时是 1GB。所以我需要找到一种方法,首先将此字符串返回给客户端,然后通过逻辑等待。他们都应该在“停止”IF内。
-
Ant 我也用这两种缺失的方法更新了我的问题。