要確保我做的一切正確的,在幫助別人了,我決定創建一個測試應用程序上傳文件的希望和張貼在這裏在我的問題上尋求幫助。希望它可以幫助別人,同時幫助我! ;)使用本地.NET庫FTP進度條不顯示正確的進度
值得注意: - 我測試這種通過速度較慢的連接,並限制了FTP用戶帳戶的速度約爲10KB/s的只是測試了這一點。
問題: 當使用我的新創建的線程(功能UploadAFile-> UF_Thread)上傳文件,我在剪斷,它的下方,發送一個數據包,即使requestStream.Write()返回時,允許線程繼續我的服務器顯示數據包仍在發送。在發送100個數據包3秒鐘的時間內,在我的循環中發送所有數據包,同時在服務器上傳輸文件需要大約26秒(在這段時間,我的應用程序剛剛坐下並等待它完成,顯示沒有進度完全是因爲23秒前它根據GUI完成)。
預期結果: 我需要找到一種方法來設置bStillSending爲真,直到數據包完成。我想等待每個數據包。
開始剪斷,它
DateTime startTimestamp = DateTime.Now;
requestStream.Write(buffer, 0, bytesRead);
//Wait for packet to get to server
bool bStillSending = false;
do
{
Thread.Sleep(50);
} while (bStillSending);
bytesRead = sourceStream.Read(buffer, 0, ufParams.PacketSize);
lBytesSent += bytesRead;
TimeSpan tsUploadTime = DateTime.Now.Subtract(startTimestamp);
if (tsUploadTime.Milliseconds > 0) lstSpeedInBytesPerMillisecond.Add(bytesRead/tsUploadTime.Milliseconds);
else lstSpeedInBytesPerMillisecond.Add(bytesRead);
sSpeed = ConvertBytesToLargestType(lstSpeedInBytesPerMillisecond.Last());
Raise_UploadFile_Progress_Event(bytesRead, lBytesSent, sourceStream.Length, sSpeed);
年底剪斷,它
啓動整個應用程序的
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Threading;
using System.Windows;
namespace WindowsFormsApplication1
{
class UploadFile
{
#region Private class variables
private ManualResetEvent m_MRE_StopUpload = new ManualResetEvent(false);
#endregion
#region Private class structures
private class UploadFile_PARAMS
{
#region Local private class variables
private int m_iThreadID = 0;
private ManualResetEvent m_MRE_StopUpload = new ManualResetEvent(false);
private string m_sServer = "";
private string m_sUser = "";
private string m_sPass = "";
private string m_sSourcePath = "";
private string m_sDestPath = "";
private int m_iPacketSize = 512;
#endregion
#region Properties
public int ThreadID
{
get
{
return m_iThreadID;
}
set
{
m_iThreadID = value;
}
}
public ManualResetEvent MRE_StopUpload
{
get
{
return m_MRE_StopUpload;
}
set
{
m_MRE_StopUpload = value;
}
}
public string Server
{
get
{
return m_sServer;
}
set
{
m_sServer = value;
}
}
public string User
{
get
{
return m_sUser;
}
set
{
m_sUser = value;
}
}
public string Pass
{
get
{
return m_sPass;
}
set
{
m_sPass = value;
}
}
public string SourcePath
{
get
{
return m_sSourcePath;
}
set
{
m_sSourcePath = value;
}
}
public string DestPath
{
get
{
return m_sDestPath;
}
set
{
m_sDestPath = value;
}
}
public int PacketSize
{
get
{
return m_iPacketSize;
}
set
{
m_iPacketSize = value;
}
}
#endregion
}
#endregion
#region Public class methods
//Public method UploadFile
public void UploadSingleFile(string sServer, string sUser, string sPass, string sSourcePath, string sDestPath, int iPacketSize)
{
UploadFile_PARAMS ufParams = new UploadFile_PARAMS();
ufParams.Server = sServer;
ufParams.User = sUser;
ufParams.Pass = sPass;
ufParams.SourcePath = sSourcePath;
ufParams.DestPath = sDestPath;
ufParams.PacketSize = iPacketSize;
ufParams.MRE_StopUpload = m_MRE_StopUpload;
UploadAFile(ufParams);
}
//Public method CancelUpload
public void CancelUpload()
{
m_MRE_StopUpload.Set();
}
#endregion
#region Public class events
//Public event UploadFile_Progress
public delegate void UploadFile_Progress_EventHandler(long lBytesSent, long lTotalBytesSent, long lTotalFileSizeBytes, string sSpeed);
public event UploadFile_Progress_EventHandler UploadFile_Progress;
private void Raise_UploadFile_Progress_Event(long lBytesSent, long lTotalBytesSent, long lTotalFileSizeBytes, string sSpeed)
{
if (this.UploadFile_Progress != null)
{
//The event handler exists so raise the event to it
this.UploadFile_Progress(lBytesSent, lTotalBytesSent, lTotalFileSizeBytes, sSpeed);
}
}
//Public event UploadFile_Complete
public delegate void UploadFile_Complete_EventHandler(long lTotalBytesSent, long lTotalFileSizeBytes, bool bError, string sAverageSpeed, TimeSpan tsTimeItTookToUpload);
public event UploadFile_Complete_EventHandler UploadFile_Complete;
private void Raise_UploadFile_Complete_Event(long lTotalBytesSent, long lTotalFileSizeBytes, bool bError, string sAverageSpeed, TimeSpan tsTimeItTookToUpload)
{
if (this.UploadFile_Complete != null)
{
//The event handler exists so raise the event to it
this.UploadFile_Complete(lTotalBytesSent, lTotalFileSizeBytes, bError, sAverageSpeed, tsTimeItTookToUpload);
}
}
//Public event UploadFile_Error
public delegate void UploadFile_Error_EventHandler(string sErrorMessage);
public event UploadFile_Error_EventHandler UploadFile_Error;
private void Raise_UploadFile_Error_Event(string sErrorMessage)
{
if (this.UploadFile_Error != null)
{
//The event handler exists so raise the event to it
this.UploadFile_Error(sErrorMessage);
}
}
#endregion
#region Private class functions
//Private class function ConvertBytesToLargestType
private string ConvertBytesToLargestType(long lBytesAMillisecond)
{
//Convert the byte count to the highest type
double dKiloBytesAMillisecond = (double)lBytesAMillisecond/(double)1024;
double dMegaBytesAMillisecond = dKiloBytesAMillisecond/(double)1024;
double dGigaBytesAMillisecond = dMegaBytesAMillisecond/(double)1024;
if (dGigaBytesAMillisecond >= 1)
{
return dGigaBytesAMillisecond.ToString("#.##") + "Gb/s";
}
if (dMegaBytesAMillisecond >= 1)
{
return dMegaBytesAMillisecond.ToString("#.##") + "Mb/s";
}
if (dKiloBytesAMillisecond >= 1)
{
return dKiloBytesAMillisecond.ToString("#") + "kb/s";
}
return lBytesAMillisecond.ToString("#") + "b/s";
}
#endregion
#region Private class multi-threading functions
//Thread creation for UploadAFile
System.Threading.Thread threadUF;
private void UploadAFile(UploadFile_PARAMS ufParams)
{
//Make sure to destory any old objects
if (threadUF != null)
{
if (threadUF.IsAlive) threadUF.Abort();
while (threadUF.IsAlive) Application.DoEvents();
threadUF = null;
GC.Collect();
}
//Make sure the params object is not null
if (ufParams == null) return;
//Create the new thread
threadUF = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(UF_Thread));
threadUF.IsBackground = true;
ufParams.ThreadID = threadUF.ManagedThreadId;
//Start the thread
threadUF.Start(ufParams);
}
private void UF_Thread(Object oParameter)
{
//Extract (cast) the params
UploadFile_PARAMS ufParams = (UploadFile_PARAMS)oParameter;
FtpWebRequest request;
FtpWebResponse response;
Stream sourceStream = new MemoryStream();
Stream requestStream = sourceStream;
long lBytesSent = 0;
string sSpeed = "";
TimeSpan tsTimeToUploadFile;
DateTime dtStartedUpload = DateTime.Now;
List<long> lstSpeedInBytesPerMillisecond = new List<long>();
try
{
request = (FtpWebRequest)WebRequest.Create("ftp://" + ufParams.Server + ufParams.DestPath);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(ufParams.User, ufParams.Pass);
sourceStream = new FileStream(ufParams.SourcePath, FileMode.Open);
requestStream = request.GetRequestStream();
request.ContentLength = sourceStream.Length;
byte[] buffer = new byte[ufParams.PacketSize];
int bytesRead = sourceStream.Read(buffer, 0, ufParams.PacketSize);
do
{
DateTime startTimestamp = DateTime.Now;
requestStream.Write(buffer, 0, bytesRead);
//Wait for packet to get to server
bool bStillSending = false;
do
{
Thread.Sleep(50);
} while (bStillSending);
bytesRead = sourceStream.Read(buffer, 0, ufParams.PacketSize);
lBytesSent += bytesRead;
TimeSpan tsUploadTime = DateTime.Now.Subtract(startTimestamp);
if (tsUploadTime.Milliseconds > 0) lstSpeedInBytesPerMillisecond.Add(bytesRead/tsUploadTime.Milliseconds);
else lstSpeedInBytesPerMillisecond.Add(bytesRead);
sSpeed = ConvertBytesToLargestType(lstSpeedInBytesPerMillisecond.Last());
Raise_UploadFile_Progress_Event(bytesRead, lBytesSent, sourceStream.Length, sSpeed);
} while (bytesRead > 0 && ufParams.MRE_StopUpload.WaitOne(0) == false);
if (ufParams.MRE_StopUpload.WaitOne(0)) throw new System.Net.WebException("Upload was canceled!");
//Close the stream to show we are finished with the file
requestStream.Close();
response = (FtpWebResponse)request.GetResponse();
if (lstSpeedInBytesPerMillisecond.Count > 0)
{
sSpeed = ConvertBytesToLargestType(Convert.ToInt64(lstSpeedInBytesPerMillisecond.Average()));
}
else sSpeed = "0 b/s";
tsTimeToUploadFile = DateTime.Now.Subtract(dtStartedUpload);
Raise_UploadFile_Complete_Event(lBytesSent, sourceStream.Length, false, sSpeed, tsTimeToUploadFile);
}
catch (Exception ex)
{
Raise_UploadFile_Error_Event(ex.GetType().Name + ": " + ex.Message);
if (lstSpeedInBytesPerMillisecond.Count > 0)
{
sSpeed = ConvertBytesToLargestType(Convert.ToInt64(lstSpeedInBytesPerMillisecond.Average()));
}
else sSpeed = "0 b/s";
tsTimeToUploadFile = DateTime.Now.Subtract(dtStartedUpload);
Raise_UploadFile_Complete_Event(lBytesSent, sourceStream.Length, true, sSpeed, tsTimeToUploadFile);
}
finally
{
request = null;
sourceStream.Close();
sourceStream = null;
requestStream.Close();
requestStream = null;
}
}
#endregion
}
public partial class Form1 : Form
{
//Define the upload object as a global form object
UploadFile upload;
public Form1()
{
InitializeComponent();
}
#region Buttons
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.InitialDirectory = "c:\\";
openFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
openFileDialog1.FilterIndex = 2;
openFileDialog1.RestoreDirectory = true;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
if (File.Exists(openFileDialog1.FileName))
{
label1.Text = openFileDialog1.FileName;
listView1.Items.Add("Selected file to upload.");
}
else
{
label1.Text = "";
listView1.Items.Add("File choosen does not exist!");
}
}
}
private void button2_Click(object sender, EventArgs e)
{
if (!File.Exists(label1.Text))
{
listView1.Items.Add(DateTime.Now.ToString("hh:mm:ss:f") + " Error! File selected does not exist!");
return;
}
listView1.Items.Add(DateTime.Now.ToString("hh:mm:ss:f") + " Starting the upload process...");
progressBar1.Minimum = 0;
progressBar1.Maximum = 100;
upload = new UploadFile();
upload.UploadFile_Progress += new UploadFile.UploadFile_Progress_EventHandler(upload_UploadFile_Progress);
upload.UploadFile_Complete += new UploadFile.UploadFile_Complete_EventHandler(upload_UploadFile_Complete);
upload.UploadFile_Error += new UploadFile.UploadFile_Error_EventHandler(upload_UploadFile_Error);
upload.UploadSingleFile("ftp.xentar.com", "arvo", "S1mP13", label1.Text, "/arvo/" + Path.GetFileName(label1.Text), 1024);
}
private void button3_Click(object sender, EventArgs e)
{
listView1.Items.Add(DateTime.Now.ToString("hh:mm:ss:f") + " Canceling upload...");
upload.CancelUpload();
}
#endregion
#region UploadFile object events
private void upload_UploadFile_Error(string sErrorMessage)
{
listView1.Items.Add(DateTime.Now.ToString("hh:mm:ss:f") + " Error! " + sErrorMessage);
}
private void upload_UploadFile_Complete(long lTotalBytesSent, long lTotalFileSizeBytes, bool bError, string sAverageSpeed, TimeSpan tsTimeItTookToUpload)
{
if (bError)
{
AddItemToLog("Error uploading file!");
}
else
{
AddItemToLog("Upload complete!");
AddItemToLog("It took " + tsTimeItTookToUpload.ToString("mm") + " minutes and " + tsTimeItTookToUpload.ToString("ss") + " seconds to upload the file.");
UpdateProgressBar(100, lTotalBytesSent);
}
}
private void upload_UploadFile_Progress(long lBytesSent, long lTotalBytesSent, long lTotalFileSizeBytes, string sSpeed)
{
int iProgressComplete = Convert.ToInt32(((double)lTotalBytesSent/(double)lTotalFileSizeBytes) * 100);
UpdateProgressBar(iProgressComplete, lTotalBytesSent);
}
#endregion
#region Thread-safe functions
private void AddItemToLog(string sLogEntry)
{
//Send to tread safe call
ThreadSafe_AddItemToLog(sLogEntry);
}
delegate void ThreadSafe_AddItemToLog_Callback(string sLogEntry);
private void ThreadSafe_AddItemToLog(string sLogEntry)
{
if (this.InvokeRequired)
{
ThreadSafe_AddItemToLog_Callback d =
new ThreadSafe_AddItemToLog_Callback(ThreadSafe_AddItemToLog);
try
{
this.Invoke(d, new object[] { sLogEntry });
}
catch
{
//ObjectDisposedException
}
}
else
{
//Send the call on to the normal function
ThreadSafe_AddItemToLog_Proc(sLogEntry);
}
}
private void ThreadSafe_AddItemToLog_Proc(string sLogEntry)
{
listView1.Items.Add(DateTime.Now.ToString("hh:mm:ss:f") + " " + sLogEntry);
}
private void UpdateProgressBar(int iProgressBarValue, long lTotalBytesSent)
{
//Send to tread safe call
ThreadSafe_UpdateProgressBar(iProgressBarValue, lTotalBytesSent);
}
delegate void ThreadSafe_UpdateProgressBar_Callback(int iProgressBarValue, long lTotalBytesSent);
private void ThreadSafe_UpdateProgressBar(int iProgressBarValue, long lTotalBytesSent)
{
if (this.InvokeRequired)
{
ThreadSafe_UpdateProgressBar_Callback d =
new ThreadSafe_UpdateProgressBar_Callback(ThreadSafe_UpdateProgressBar);
try
{
this.Invoke(d, new object[] { iProgressBarValue, lTotalBytesSent });
}
catch
{
//ObjectDisposedException
}
}
else
{
//Send the call on to the normal function
ThreadSafe_UpdateProgressBar_Proc(iProgressBarValue, lTotalBytesSent);
}
}
private void ThreadSafe_UpdateProgressBar_Proc(int iProgressBarValue, long lTotalBytesSent)
{
label4.Text = lTotalBytesSent.ToString();
progressBar1.Value = iProgressBarValue;
}
#endregion
}
}
沒有必要對中的DoEvents工作者線程中調用,因爲它不會有任何。 GUI將擁有自己的線程。 – Deanna 2012-07-15 12:29:30
我看不到通過以下方式獲取實際上傳進度的方法:| – Deanna 2012-07-15 12:45:02
是啊迪安娜嘿嘿,你和喬伊兩人都讓我對這些的DoEvents地獄......我恨他們也和不使用它們!這只是我試圖測試的東西,我已經瞭解到,如果一個工作線程返回上傳進度(將更新事件發送到主線程),它使主線程沒有時間更新。如果我在工作線程中有doevents,它似乎會減慢它的速度,使主線程趕上「動畫」進度條。無論如何,這只是一個考驗。我可以很好地使用Thread.Sleep(500)。 ;)所以沒有解決方案吧。 :/ – 2012-07-15 22:16:25