I am working on file transfer software. But progress bar shows 100% directly not showing actual progress. So do i need to change my method to write file. Or there is some silly mistake. Here is my code. Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Media;
using System.Threading;
namespace Sender2
{
public partial class Form1 : Form
{
private Thread thrDownload;
private static int PercentProgress;
private delegate void UpdateProgessCallback(Int64 BytesRead, Int64 TotalBytes);
public Form1()
{
InitializeComponent();
}
private void Browse_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
txtSelectFilePath.Text = openFileDialog1.FileName;
String path1=txtSelectFilePath.Text;
files_list.Items.Add(path1);
files_list.View = View.List;
}
}
private void UpdateProgress(Int64 BytesRead, Int64 TotalBytes)
{
PercentProgress = Convert.ToInt32((BytesRead * 100) / TotalBytes);
progressBar1.Value = PercentProgress;
lblProgress.Text = "Downloaded " + BytesRead + " out of " + TotalBytes + " (" + PercentProgress + "%)";
}
private void Send_Click(object sender, EventArgs e)
{
TransferService2.TransferService2Client client = new TransferService2.TransferService2Client();
foreach(ListViewItem item in files_list.Items)
{
TransferService2.File file = client.DownloadDocument(item.Text);
System.IO.FileStream fs = new System.IO.FileStream(@"c:\DownloadedFiles\" + file.Name, System.IO.FileMode.Create);
Int64 fileSize = file.Content.Length;
int bytesSize = 0;
byte[] downBuffer = new byte[2048];
int pos = 0;
int length = 128;
while (pos < file.Content.Length)
{
if (length > (file.Content.Length - pos))
{
length = file.Content.Length - pos;
}
fs.Write(file.Content, pos, length);
this.Invoke(new UpdateProgessCallback(this.UpdateProgress), new object[] { file.Content.Length, fileSize });
pos = pos + length;
}
MessageBox.Show(file.Name + " is downloaded");
}
}
}
}
TransferService2.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace TransferService2
{
public class TransferService2 : ITransferService2
{
public File DownloadDocument(String filepath)
{
File file = new File();
String path = filepath;
byte[] buffer;
FileStream fs = new FileStream(@path, FileMode.Open, FileAccess.Read);
try
{
int length = (int)fs.Length;
buffer = new byte[length];
int count;
int sum = 0;
while((count=fs.Read(buffer,sum,length-sum))>0)
{
sum = sum + count;
}
}
finally
{
fs.Close();
}
file.Content = buffer;
file.Name = Path.GetFileName(path);
return file;
}
}
}
ITransferService2.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace TransferService2
{
[ServiceContract]
public interface ITransferService2
{
[OperationContract]
File DownloadDocument(String filepath);
}
[DataContract]
public class File
{
[DataMember]
public string Name { get; set; }
[DataMember]
public byte[] Content { get; set; }
}
}
As I mentioned in the comments, you are performing the whole operation synchronously on the UI thread, hence it's busy and cannot update during the processing.
You need to let the operation execute asynchronously. There are many ways to do that, here is one possible way using async/await
:
private async void Send_Click(object sender, EventArgs e)
{
TransferService2.TransferService2Client client = new TransferService2.TransferService2Client();
foreach(ListViewItem item in files_list.Items)
{
TransferService2.File file = await Task.Run(() => client.DownloadDocument(item.Text));
System.IO.FileStream fs = new System.IO.FileStream(@"c:\DownloadedFiles\" + file.Name, System.IO.FileMode.Create);
Int64 fileSize = file.Content.Length;
int bytesSize = 0;
byte[] downBuffer = new byte[2048];
int pos = 0;
int length = 128;
while (pos < file.Content.Length)
{
if (length > (file.Content.Length - pos))
{
length = file.Content.Length - pos;
}
await fs.WriteAsync(file.Content, pos, length);
// Here the await will resume on the UI thread, so no Invoke is needed
pos = pos + length;
this.UpdateProgress(pos, fileSize);
}
MessageBox.Show(file.Name + " is downloaded");
}
}