Progressbar in Windows Phone 8.1 - c#

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

Related

How to increase progressbar while downloading file using Sftp (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;

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

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].

How to chunk and stream a file

I need to simulate a stream using a file...
This is what I was able to produce so far... the code works, but the streaming does not occur.
I have no experience with streams, so expect to find lot of bugs.
Stream chunkedStream = new MemoryStream();
var task = session.AnalyzeAsync(chunkedStream);
FillStream(chunkedStream);
while (!task.Wait(500))
{
Console.Write("\r" + ((float)chunkedStream.Position / 16000) + " Seconds");
if (!chunkedStream.CanWrite)
{
break;
}
}
private static async Task FillStream(Stream chunkedStream)
{
var stream = Properties.Resources.ResourceManager.GetStream("Sample");
byte[] chunk = new byte[16000];
while (true)
{
Thread.Sleep(1000);
int index = 0;
// There are various different ways of structuring this bit of code.
// Fundamentally we're trying to keep reading in to our chunk until
// either we reach the end of the stream, or we've read everything we need.
while (index < chunk.Length)
{
int bytesRead = stream.Read(chunk, index, chunk.Length - index);
if (bytesRead == 0)
{
break;
}
index += bytesRead;
}
if (index != 0) // Our previous chunk may have been the last one
{
// SendChunk(chunk, index); // index is the number of bytes in the chunk
chunkedStream.Write(chunk, 0, chunk.Length);
}
if (index != chunk.Length) // We didn't read a full chunk: we're done
{
chunkedStream.Close();
return;
}
}
}
public async Task AnalyzeAsync(Stream voiceStream)
{
IntervalHandler();
_StreamTask = UpStreamVoiceData(voiceStream);
await _StreamTask;
}
private async Task<Result<AnalysisResult>> UpStreamVoiceData(Stream voiceStream)
{
HttpWebRequest webRequest = WebRequestExtensions.CreateJsonPostRequest(_actions.upStream);
webRequest.ReadWriteTimeout = 1000000;
webRequest.Timeout = 10000000;
webRequest.SendChunked = true;
webRequest.AllowWriteStreamBuffering = false;
webRequest.AllowReadStreamBuffering = false;
using (var requeststream = webRequest.GetRequestStream())
{
await voiceStream.CopyStreamWithAutoFlush(requeststream);
requeststream.Close();
}
return webRequest.ReadJsonResponseAs<Result<AnalysisResult>>();
}

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