How to increase progressbar while downloading file using Sftp (C#) - c#

This code execute well. But didn't increase progressBar1.value
using (var client = new SftpClient(host, port, username, password))
{
client.Connect();
using (var fileStream = new FileStream(localFilePath, FileMode.Create))
{
var sftpFileStream = client.OpenRead(remoteFilePath);
var fileLength = client.GetAttributes(remoteFilePath).Size;
var buffer = new byte[1024];
var totalBytesRead = 0L;
var bytesRead = 0;
while ((bytesRead = sftpFileStream.Read(buffer, 0, buffer.Length)) > 0)
{
fileStream.Write(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
var progress = (double)totalBytesRead / fileLength;
progressBar1.Invoke((MethodInvoker)delegate
{
progressBar1.Value = (int)progress;
});
}
}
client.Disconnect();
}
I tried without Invoke
...
...
var progress = (double)totalBytesRead / fileLength;
progressBar1.Invoke((MethodInvoker)delegate
progressBar1.Value = (int)progress;
Both way didn't work. How can I fix this?

You set the value of the progress bar within the range 0.0 to 1.0: progress = (double)totalBytesRead / fileLength;. This has to match the mininum and maximum value as set at the progress bar control. So
either set the maximum value of the progress bar control to 1
or leave it at 100 and set the value as progress = 100.0 * totalBytesRead / fileLength;

Related

C# TCP Socket file transfer chunk by chunk not working with files that are above 5mbs

So I have this file transfer function that I made which works fine with small files but does not work with big files (above 5 or 10mbs). Basically what I do is I split the file into chunks and add a 'header' which defines what type of data it is so that the client can understand. I am also using this 'header' approach because I also want to be able to upload files and do other stuff at the same time. The problem is that the client is receiving half of the bytes even tho the server is sending all the bytes so I am assuming the header gets corrupted and if (header == "s^") return false.
Here is my code
Server (Uploader):
int max_buffer = 1024 * 1024 * 2;
using (var fs = new FileStream(fo_path, FileMode.Open, FileAccess.Read))
{
byte[] header = Encoding.Unicode.GetBytes("s^fd");
byte[] buffer = new byte[max_buffer];
int bytesRead = 0;
long bytesToRead = fs.Length;
while (bytesToRead > 0)
{
int n = fs.Read(buffer, 0, max_buffer);
if (n == 0) break;
if (n != buffer.Length)
Array.Resize(ref buffer, n);
byte[] data = new byte[header.Length + n];
Buffer.BlockCopy(header, 0, data, 0, header.Length);
Buffer.BlockCopy(buffer, 0, data, header.Length, n);
_client.Send(data);
bytesRead += n;
bytesToRead -= n;
}
}
Client (Downloader):
private static MemoryStream fileStream = new MemoryStream(); //global scope
byte[] buffer = new byte[2048];
int recieved = _clientSocket.Receive(buffer, SocketFlags.None);
if (recieved == 0) return;
byte[] data = new byte[recieved];
Array.Copy(buffer, data, recieved);
string header = Encoding.Unicode.GetString(data, 0, 4);
if (header == "s^")
{
string header_cmd = Encoding.Unicode.GetString(data, 4, 4);
if (header_cmd == "fd")
{
byte[] fileBytes = new byte[data.Length - 32];
Buffer.BlockCopy(data, 32, fileBytes, 0, fileBytes.Length);
fileStream.Write(fileBytes, 0, fileBytes.Length);
fo_writeSize += fileBytes.Length;
if (fo_writeSize >= fo_size) //fo_size is the file size that the server sends before sending the actual file itself
{
var fs = new FileStream(fo_path, FileMode.Create, FileAccess.Write);
fileStream.WriteTo(fs);
fileStream.Close();
fs.Close();
}
}
}

How can I improve the performance of this CopyTo method?

EDIT: I have now solved this. My answer posted below and will mark as solved when SO lets me.
I have a CopyTo (and a CopyToAsync) method to copy files in my C# application.
I have found that it is actually quite slow to copy the files, compared to something like Xcopy.
I extracted the core functionality of the copy method and placed it into a test console app to get the speed that it operates at versus Xcopy, and found the results actually quite different.
The results I get are:
Async Method: 36.59 seconds - Average speed: 1512.63 mb/sec
Sync Method: 36.49 seconds - Average speed: 1516.72 mb/sec
XCOPY: 5.62 seconds - Average speed: 9842.11 mb/sec
All three of these used the exact same file, and the exact same destination.
StreamExtensions class:
public static class StreamExtensions
{
const int DEFAULT_BUFFER = 0x1000; // 4096 bits
public static async Task CopyToAsync(this Stream source, Stream destination, IProgress<long> progress, CancellationToken cancellationToken = default, int bufferSize = DEFAULT_BUFFER)
{
var buffer = new byte[bufferSize];
int bytesRead;
long totalRead = 0;
while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) > 0)
{
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken);
cancellationToken.ThrowIfCancellationRequested();
totalRead += bytesRead;
progress.Report(totalRead);
}
}
public static void CopyTo(this Stream source, Stream destination, IProgress<long> progress, int bufferSize = DEFAULT_BUFFER)
{
var buffer = new byte[bufferSize];
int bytesRead;
long totalRead = 0;
while ((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0)
{
destination.Write(buffer, 0, bytesRead);
totalRead += bytesRead;
progress.Report(totalRead);
}
}
}
The IProgress<long> object is to report the file progress back to the calling method.
Example call implementation:
// Asynchronous version
public static async Task CopyFileSetAsync(Dictionary<string, string> fileSet)
{
for (var x = 0; x < fileSet.Count; x++)
{
var item = fileSet.ElementAt(x);
var from = item.Key;
var to = item.Value;
int currentProgress = 0;
long fileSize = new FileInfo(from).Length;
IProgress<long> progress = new SynchronousProgress<long>(value =>
{
decimal fileProg = (decimal)(value * 100) / fileSize;
if (fileProg != currentProgress)
{
currentProgress = (int)fileProg;
OnUpdateFileProgress(null, new FileProgressEventArgs(fileProg));
}
});
using (var outStream = new FileStream(to, FileMode.Create, FileAccess.Write, FileShare.Read))
{
using (var inStream = new FileStream(from, FileMode.Open, FileAccess.Read, FileShare.Read))
{
await inStream.CopyToAsync(outStream, progress);
}
}
OnUpdateFileProgress(null, new FileProgressEventArgs(100)); // Probably redundant
}
}
// Synchronous version
public static void CopyFileSet(Dictionary<string, string> fileSet)
{
for (var x = 0; x < fileSet.Count; x++)
{
var item = fileSet.ElementAt(x);
var from = item.Key;
var to = item.Value;
int currentProgress = 0;
long fileSize = new FileInfo(from).Length;
IProgress<long> progress = new SynchronousProgress<long>(value =>
{
decimal fileProg = (decimal)(value * 100) / fileSize;
if (fileProg != currentProgress)
{
currentProgress = (int)fileProg;
OnUpdateFileProgress(null, new FileProgressEventArgs(fileProg));
}
});
using (var outStream = new FileStream(to, FileMode.Create, FileAccess.Write, FileShare.Read))
{
using (var inStream = new FileStream(from, FileMode.Open, FileAccess.Read, FileShare.Read))
{
inStream.CopyTo(outStream, progress, 1024);
}
}
OnUpdateFileProgress(null, new FileProgressEventArgs(100)); // Probably redundant
}
}
Is there something that's preventing this from running as fast as it could? I'm just stumped as to how much slower it is compared to copy.
EDIT: Fixed a typo where I forgot a single ` around IProgress
Thanks to Tom and xanatos, I answered my own question:
I misunderstood the impact of buffer size. I had only gone so far as 8192 bytes as the buffer size. After taking on their suggestions, I increased the buffer size to 1mb (1048576 bytes), and this made a massive difference to the performance.
Async Method: 5.57 seconds - Average speed: 9938.68 mb/sec
Sync Method: 5.52 seconds - Average speed: 10028.36 mb/sec
XCOPY: 5.03 seconds - Average speed: 11007.84 mb/sec

Progressbar in Windows Phone 8.1

I am trying to make my progressbar work in Windows phone 8.1.
Here is my code :
using (var writeStream = await newZipFile.OpenAsync(FileAccessMode.ReadWrite))
{
using (var outputStream = writeStream.GetOutputStreamAt(0))
{
using (var dataWriter = new DataWriter(outputStream))
{
using (Stream input = webResponse.GetResponseStream())
{
long totalSize = 0;
int read;
uint zeroUint = Convert.ToUInt32(0);
uint readUint;
while ((read = input.Read(buffer, 0, buffer.Length)) >0)
{
// totalSize += read;
totalSize = totalSize + read;
//pb2.Value = totalSize * 100 / sizeFit;
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
//Declaration of variables
// load.progresschanged(totalSize * 100 / sizeFit);
pb2.Value = totalSize * 100 / sizeFit;
});
readUint = Convert.ToUInt32(read);
IBuffer ibuffer = buffer.AsBuffer();
dataWriter.WriteBuffer(ibuffer, zeroUint, readUint);
}
await dataWriter.StoreAsync();
await outputStream.FlushAsync();
dataWriter.DetachStream();
}
}
}
}
The problem here is that progressbar updates only when the value is 100.
Any help appreciated.
1)Make sure the maxvalue of progressbar is 100 in view.
2) pb2.Value = sizeFit * 100 / totalSize; Might be you are calculating the percentage wrong. Since I am not able to find sizeFit value in your code why not place a breakpoint and check whats the value being returned

Process buffer in chunk sizes

I have an IRandomAccessStream to store data on WindowsPhone 8.1 and I want to process the data in a certain BLOCKSIZE.
Here is the code
in the capture function:
await this.mediaCapture.StartRecordToStreamAsync(recordProfile, this.message);
in the stop function, when done I stop:
await this.mediaCapture.StopRecordAsync();
using (var dataReader = new DataReader(message.GetInputStreamAt(0)))
{
dataReader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
dataReader.ByteOrder = Windows.Storage.Streams.ByteOrder.LittleEndian;
// await dataReader.LoadAsync((uint)message.Size);
await dataReader.LoadAsync(((uint)message.Size + (int)FREQUENCY) * 10);
byte[] buffer = new byte[((int)message.Size + (int)FREQUENCY) * 10];
dataReader.ReadBytes(buffer);
short[] signal = new short[BLOCKSIZE];
int bufferReadResult = 0;
while (bufferReadResult != buffer.Length)
{
for (int index = 0; index < BLOCKSIZE; index += 2, bufferReadResult++)
{
signal[bufferReadResult] = BitConverter.ToInt16(buffer, index);
}
// .....process the signal[] in BLOCKSIZE,
// keep processing BLOCKSIZE until end of buffer
// so process [BLOCKSIZE][BLOCKSIZE]..............buffer end
}
}
The problem is that when bufferReadResult reaches BLOCKSIZE that's it. It won't continue with a new block unit end of buffer.
What is the best way to do this? I have a buffer or IRandomAccessStream and I want to process the all the data in chunks of short[BLOCKSIZE].

playing sound with SlimDX and DirectSound (C#)

(apologies if this is a duplicate ... i posted but saw no evidence that it actually made it to the forum)
I've been trying to get SlimDX DirectSound working. Here's the code I have. It fills the secondary buffer from a wav file and then, in a thread loop, alternately fills the lower or upper halves of the buffer.
It plays the first load of the buffer fine. The AutoResetEvents fire when they should and the lower half then upper half of the buffer are populated (verified with Debug statements). But playing does not continue after the first load of the buffer. So somehow the repopulation of the buffer doesn't work as it should.
Ideas?
(I'm using DirectSound because it's the only way I've found to set the guid of the audio device that I want to use. Am open to other .NET-friendly approaches.)
private void PlaySound(Guid soundCardGuid, string audioFile) {
DirectSound ds = new DirectSound(soundCardGuid);
ds.SetCooperativeLevel(this.Handle, CooperativeLevel.Priority);
WaveFormat format = new WaveFormat();
format.BitsPerSample = 16;
format.BlockAlignment = 4;
format.Channels = 2;
format.FormatTag = WaveFormatTag.Pcm;
format.SamplesPerSecond = 44100;
format.AverageBytesPerSecond = format.SamplesPerSecond * format.BlockAlignment;
SoundBufferDescription desc = new SoundBufferDescription();
desc.Format = format;
desc.Flags = BufferFlags.GlobalFocus;
desc.SizeInBytes = 8 * format.AverageBytesPerSecond;
PrimarySoundBuffer pBuffer = new PrimarySoundBuffer(ds, desc);
SoundBufferDescription desc2 = new SoundBufferDescription();
desc2.Format = format;
desc2.Flags = BufferFlags.GlobalFocus | BufferFlags.ControlPositionNotify | BufferFlags.GetCurrentPosition2;
desc2.SizeInBytes = 8 * format.AverageBytesPerSecond;
SecondarySoundBuffer sBuffer1 = new SecondarySoundBuffer(ds, desc2);
NotificationPosition[] notifications = new NotificationPosition[2];
notifications[0].Offset = desc2.SizeInBytes / 2 + 1;
notifications[1].Offset = desc2.SizeInBytes - 1; ;
notifications[0].Event = new AutoResetEvent(false);
notifications[1].Event = new AutoResetEvent(false);
sBuffer1.SetNotificationPositions(notifications);
byte[] bytes1 = new byte[desc2.SizeInBytes / 2];
byte[] bytes2 = new byte[desc2.SizeInBytes];
Stream stream = File.Open(audioFile, FileMode.Open);
Thread fillBuffer = new Thread(() => {
int readNumber = 1;
int bytesRead;
bytesRead = stream.Read(bytes2, 0, desc2.SizeInBytes);
sBuffer1.Write<byte>(bytes2, 0, LockFlags.None);
sBuffer1.Play(0, PlayFlags.None);
while (true) {
if (bytesRead == 0) { break; }
notifications[0].Event.WaitOne();
bytesRead = stream.Read(bytes1, 0, bytes1.Length);
sBuffer1.Write<byte>(bytes1, 0, LockFlags.None);
if (bytesRead == 0) { break; }
notifications[1].Event.WaitOne();
bytesRead = stream.Read(bytes1, 0, bytes1.Length);
sBuffer1.Write<byte>(bytes1, desc2.SizeInBytes / 2, LockFlags.None);
}
stream.Close();
stream.Dispose();
});
fillBuffer.Start();
}
}
You haven't set it to loop on the play buffer. Change your code to:
sBuffer1.Play(0, PlayFlags.Looping);

Categories

Resources