クライアントの要求に従って、webclient から継承する通信クラスを作成しました。彼らは、3 つのプロパティを実装するインターフェイスを作成するのではなく、「カスタム ウィンドウ フォームをプログレス バーとして渡す」ことができるようにしたいと考えています。とにかく、私が抱えている問題は、アプリが起動し、いわばスタートボタンをクリックすることです。これを初めて実行すると、UIスレッドがフリーズし、数秒後にフリーズが解除され、プログレスバーとデータがダウンし始めます。
ただし、この最初のフリーズの後、その後のスタートボタンの押下は完全に機能し、スレッドのアイデアをブロックしませんか?
フォーム 1 の関連するコードは次のとおりです。
private void btnSubmit_Click(object sender, EventArgs e)
{
txtResponse.Text = "";
progressForm = new ProgressFormTest();
myCommunication = new CommunicationClient(progressForm);
myCommunication.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_RequestComplete);
// myCommunication.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
myCommunication.Timeout += new EventHandler(wc_TimeOut);
myCommunication.Cancelled += new EventHandler(myCommunication_Cancelled);
progressForm.Show();
myCommunication.TimeoutValue = (int)numConnectionTimeout.Value * 1000;
myCommunication.DownloadStringAsync(new Uri(txtUrl.Text));
}
通信講座はこちら
public class CommunicationClient:WebClient
{
private int step = 1000;
private long bytesReceived;
private long bytesSent;
private Status status;
private System.Timers.Timer _timer;
private IProgress myProgressForm;
/// <summary>
/// Sets the timeout value in milliseconds
/// </summary>
public int TimeoutValue { get; set; }
public int TimeElapsed { get; set; }
public long BytesReceived
{
get
{
return bytesReceived;
}
}
public long BytesSent
{
get
{
return bytesSent;
}
}
public event EventHandler Timeout;
public event EventHandler Cancelled;
public CommunicationClient(IProgress progressForm)
{
myProgressForm = progressForm;
_timer = new System.Timers.Timer(step);
_timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
}
protected override void OnDownloadStringCompleted(DownloadStringCompletedEventArgs e)
{
_timer.Stop();
if (status == Status.Completed)
{
myProgressForm.PercentComplete = 100;
base.OnDownloadStringCompleted(e);
}
}
protected override void OnDownloadProgressChanged(DownloadProgressChangedEventArgs e)
{
bytesReceived = e.BytesReceived;
myProgressForm.BytesReceived = bytesReceived;
if (e.TotalBytesToReceive == -1)
myProgressForm.PercentComplete = calculateFakePercentage();
else
myProgressForm.PercentComplete = e.ProgressPercentage;
base.OnDownloadProgressChanged(e);
}
protected virtual void OnTimeout(EventArgs e)
{
if (Timeout != null)
{
CancelAsync();
this.Dispose();
Timeout(this, e);
}
}
protected virtual void OnCancelled(EventArgs e)
{
if (Cancelled != null)
{
this.Dispose();
Cancelled(this, e);
}
}
/// <summary>
/// Cancels a pending asynchronous operation and raises the Cancelled Event
/// </summary>
/// <param name="Event">Set to true to raise the event</param>
public void CancelAsync(bool Event)
{
CancelAsync();
if (Event)
{
status = Status.Cancelled;
OnCancelled(new EventArgs());
}
}
private void initialize()
{
status = Status.Completed;
TimeElapsed = 0;
_timer.Start();
}
new public void DownloadStringAsync(Uri url)
{
initialize();
base.DownloadStringAsync(url);
}
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
TimeElapsed += step;
if (TimeElapsed >= TimeoutValue)
{
_timer.Stop();
status = Status.Timeout;
OnTimeout(e);
}
}
//used when the website in question doesnt provide the content length
private int calculateFakePercentage()
{
return (int)bytesReceived * 100 / 60000 ;
}
}
そして、ここに単純なインターフェイス IProgressForm があります
public interface IProgress
{
int PercentComplete
{
get;
set;
}
long BytesReceived
{
get;
set;
}
long BytesSent
{
get;
set;
}
}