gpt4 book ai didi

c# - 等待事件结束

转载 作者:太空狗 更新时间:2023-10-29 21:46:00 31 4
gpt4 key购买 nike

我试图将网络客户端的响应转换为 Json,但它试图在完成从服务器下载之前创建 JSON 对象。有没有一种“好”的方式让我等待 WebOpenReadCompleted 被执行?

不得不提的是,这是一个 WP7 应用程序,所以一切都是异步的

public class Client
{

public String _url;
private String _response;
private WebClient _web;

private JObject jsonsobject;
private Boolean blockingCall;


private Client(String url)
{
_web = new WebClient();
_url = url;
}

public JObject Login(String username, String password)
{
String uriUsername = HttpUtility.UrlEncode(username);
String uriPassword = HttpUtility.UrlEncode(password);

Connect(_url + "/data.php?req=Login&username=" + uriUsername + "&password=" + uriPassword + "");
jsonsobject = new JObject(_response);
return jsonsobject;
}

public JObject GetUserInfo()
{

Connect(_url + "/data.php?req=GetUserInfo");
jsonsobject = new JObject(_response);
return jsonsobject;
}

public JObject Logout()
{

Connect(_url + "/data.php?req=Logout");
jsonsobject = new JObject(_response);
return jsonsobject;
}

private void Connect(String url)
{

_web.Headers["Accept"] = "application/json";
_web.OpenReadCompleted += new OpenReadCompletedEventHandler(WebOpenReadCompleted);
_web.OpenReadAsync(new Uri(url));
}

private void WebOpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error != null || e.Cancelled)
{
MessageBox.Show("Error:" + e.Error.Message);
_response = "";
}
else
{
using (var reader = new StreamReader(e.Result))
{
_response = reader.ReadToEnd();
}
}
}
}

最佳答案

您可以使用 EventWaitHandle 很好地阻塞,直到异步读取完成。我对使用 WebClient 下载文件有类似的要求。我的解决方案是子类化 WebClient。完整来源如下。具体来说,DownloadFileWithEvents 会很好地阻塞,直到异步下载完成。

根据您的目的修改类应该非常简单。

public class MyWebClient : WebClient, IDisposable
{
public int Timeout { get; set; }
public int TimeUntilFirstByte { get; set; }
public int TimeBetweenProgressChanges { get; set; }

public long PreviousBytesReceived { get; private set; }
public long BytesNotNotified { get; private set; }

public string Error { get; private set; }
public bool HasError { get { return Error != null; } }

private bool firstByteReceived = false;
private bool success = true;
private bool cancelDueToError = false;

private EventWaitHandle asyncWait = new ManualResetEvent(false);
private Timer abortTimer = null;

const long ONE_MB = 1024 * 1024;

public delegate void PerMbHandler(long totalMb);

public event PerMbHandler NotifyMegabyteIncrement;

public MyWebClient(int timeout = 60000, int timeUntilFirstByte = 30000, int timeBetweenProgressChanges = 15000)
{
this.Timeout = timeout;
this.TimeUntilFirstByte = timeUntilFirstByte;
this.TimeBetweenProgressChanges = timeBetweenProgressChanges;

this.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(MyWebClient_DownloadFileCompleted);
this.DownloadProgressChanged += new DownloadProgressChangedEventHandler(MyWebClient_DownloadProgressChanged);

abortTimer = new Timer(AbortDownload, null, TimeUntilFirstByte, System.Threading.Timeout.Infinite);
}

protected void OnNotifyMegabyteIncrement(long totalMb)
{
if (NotifyMegabyteIncrement != null) NotifyMegabyteIncrement(totalMb);
}

void AbortDownload(object state)
{
cancelDueToError = true;
this.CancelAsync();
success = false;
Error = firstByteReceived ? "Download aborted due to >" + TimeBetweenProgressChanges + "ms between progress change updates." : "No data was received in " + TimeUntilFirstByte + "ms";
asyncWait.Set();
}

void MyWebClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
if (cancelDueToError) return;

long additionalBytesReceived = e.BytesReceived - PreviousBytesReceived;
PreviousBytesReceived = e.BytesReceived;
BytesNotNotified += additionalBytesReceived;

if (BytesNotNotified > ONE_MB)
{
OnNotifyMegabyteIncrement(e.BytesReceived);
BytesNotNotified = 0;
}
firstByteReceived = true;
abortTimer.Change(TimeBetweenProgressChanges, System.Threading.Timeout.Infinite);
}

public bool DownloadFileWithEvents(string url, string outputPath)
{
asyncWait.Reset();
Uri uri = new Uri(url);
this.DownloadFileAsync(uri, outputPath);
asyncWait.WaitOne();

return success;
}

void MyWebClient_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
if (cancelDueToError) return;
asyncWait.Set();
}

protected override WebRequest GetWebRequest(Uri address)
{
var result = base.GetWebRequest(address);
result.Timeout = this.Timeout;
return result;
}

void IDisposable.Dispose()
{
if (asyncWait != null) asyncWait.Dispose();
if (abortTimer != null) abortTimer.Dispose();

base.Dispose();
}
}

关于c# - 等待事件结束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11439034/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com