I am writing a program which copies a file. I have the file copying correctly, the progress bar updates, but I get an error which states that the e.ProgressPercentage is at 101. The code for the bgWorker_ProgressChanged event handler is:
private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// We will increase the progress bar when work progress is reported.
pbCopyProgress.Maximum = 100;
pbCopyProgress.Value = e.ProgressPercentage;
}
Here is the code for the bgWorker_DoWork event handler:
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
// Gets the size of the file in bytes.
Int64 iSize = strInputFile.Length;
// Keeps track of the total bytes downloaded so we can update the progress bar.
Int64 iRunningByteTotal = 0;
// Open the input file for reading.
using (FileStream InputFile = new FileStream(strInputFile, FileMode.Open, FileAccess.Read, FileShare.None))
{
// Using the FileStream object, we can write the output file.
using (FileStream OutputFile = new FileStream(strOutputFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
// Loop the stream and get the file into the byte buffer.
int iByteSize = 0;
byte[] byteBuffer = new byte[iSize];
while ((iByteSize = InputFile.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
{
// Calculate the progress out of a base "100."
double dIndex;
double dTotal;
double dProgressPercentage;
// Write the bytes to the file system at the file path specified.
dIndex = (double)(iRunningByteTotal);
dTotal = (double)byteBuffer.Length;
dProgressPercentage = (dIndex / dTotal);
OutputFile.Write(byteBuffer, 0, iByteSize);
iRunningByteTotal += iByteSize;
intProgress = Convert.ToUInt16(dProgressPercentage);
// Update the progress bar.
bgWorker.ReportProgress(intProgress);
}
// Close the output file.
OutputFile.Close();
}
// Close the input file.
InputFile.Close();
}
}
As I said, the progress bar is updating, but I get an error because it seems to continue copying the file after it has reached 100 percent. If I put in a MessageBox.Show(Convert.ToString(intProgress)) immediately after the bgWorker.ReportProgress(intProgress) line, the dialog will pop up with 101 for the text. Any help will be greatly appreciated.
You're dividing your running total by the length of the block buffer, not the whole stream, which means the result is basically unbounded. You're failing to multiply by 100 too, but that problem is masked by the fact that the ratio is growing larger than one.
But you're making it all look very difficult - the code you want is simply:
bgWorker.ReportProgress((int)(100 * runningByteTotal / fileLength))
You should set up fileLength before the start of the loop (and it needs to be the length of the file, not the filename, as #azyberezovsky points out in his answer).
You can allow this calculation to happen with simple integer arithmetic rather than needing floating point types, as long as the multiply by 100 happens before the divide.
As a stylistic point, you don't need all the 'i's and 'd's in front of variable names - that's not considered to be good C# style. Nor are variables normally started with a capital letter - if nothing else, that confuses the SO code syntax highlighter...
That is not size of file - it is simply length of file name string:
Int64 iSize = strInputFile.Length;
And this is also not file size, this is a size of buffer you use to write data to output file:
dTotal = (double)byteBuffer.Length;
What you need is
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
using (FileStream inputFile = new FileStream(strInputFile, FileMode.Open, FileAccess.Read, FileShare.None))
using (FileStream outputFile = new FileStream(strOutputFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
long totalBytesToWrite = inputFile.Length;
long totalBytesWritten = 0;
byte[] buffer = new byte[512]; // provide any buffer size here
int bytesToWrite;
ushort percentage;
while ((bytesToWrite = inputFile.Read(buffer, 0, buffer.Length)) > 0)
{
outputFile.Write(buffer, 0, bytesToWrite);
totalBytesWritten += bytesToWrite;
percentage = (ushort)((100 * totalBytesWritten)/totalBytesToWrite);
bgWorker.ReportProgress(percentage);
}
}
}
Keep in mind - you don't need to close stream manually if you are using using block - stream will be disposed (i.e. closed) at the end of this block.
Declare maximum value of:
pbCopyProgress.Maximum = InputFile.Read(byteBuffer, 0, byteBuffer.Length)
Remove line:
percentage = (ushort)((100 * totalBytesWritten)/totalBytesToWrite);
from bgWorker_DoWork, and declare counter before while cycle in bgWorker_DoWork. For example:
int counter = 1;
before the closing brace of while increment the counter (counter++);
in bgWorker_ProgressChanged update the percentage:
pbCopyProgress.Value = e.ProgressPercentage;
If you want to fill any label with text showing the percentage the following line calculates the percentage:
int percent = 100 / (byteBuffer.Length / e.ProgressPercentage);
Label1.Text = String.Format("Passed: {0} %, percent.ToString());
Those lines should be also in bgWorker_ProgressChanged.
Related
This question already has answers here:
How to use WinForms progress bar?
(4 answers)
Closed 4 years ago.
I'm writing a simple checksum generator app using C# for large files. It's working quite fine, but users would like to see some sort of progress bar since the app freezes for a a few dozen seconds.
Here is a a sample of code I use (BufferedStream increased a lot the app performance):
private static string GetSHA5(string file)
{
using (var stream = new BufferedStream(File.OpenRead(file), 1200000))
{
var sha5 = new SHA512Managed();
byte[] checksum_sha5 = sha5.ComputeHash(stream);
return BitConverter.ToString(checksum_sha5).Replace("-", String.Empty);
}
}
My question is, is it possible to get the buffer "progress" ? Because I guess internally it operates some sort of division and looping.
I tried implementing jdweng solution but I had trouble accessing threads to update my progress bar with the position variable. In the end I rewrote my code using background_worker and a custom buffer. Here is a sample of a it.
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
dynamic data = e.Argument;
string fPath = data["file"];
byte[] buffer;
int bytesRead;
long size;
long totalBytesRead = 0;
using (Stream file = File.OpenRead(fPath))
{
size = file.Length;
progressBar1.Visible = true;
HashAlgorithm hasher = MD5.Create();
do
{
buffer = new byte[4096];
bytesRead = file.Read(buffer, 0, buffer.Length);
totalBytesRead += bytesRead;
hasher.TransformBlock(buffer, 0, bytesRead, null, 0);
backgroundWorker1.ReportProgress((int)((double)totalBytesRead / size * 100));
}
while ( bytesRead != 0) ;
hasher.TransformFinalBlock(buffer, 0, 0);
e.Result = MakeHashString(hasher.Hash);
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
private void md5HashBtn_Click(object sender, EventArgs e)
{
if (MD5TextBox.Text.Length > 0)
{
Dictionary<string, string> param = new Dictionary<string, string>();
param.Add("algo", "MD5");
param.Add("file", MD5TextBox.Text);
backgroundWorker1.RunWorkerAsync(param);
}
}
I’m developing a UWP application ( for Windows 10) which works with audio data. It receives samples buffer at the start in the form of a float array of samples, which items are changing from -1f to 1f.
Earlier I used NAudio.dll 1.8.0 that gives all necessary functionality.
Worked with WaveFileReader, waveBuffer.FloatBuffer, WaveFileWriter classes.
However, when I finished this app and tried to build Release version, got this error:
ILT0042: Arrays of pointer types are not currently supported: 'System.Int32*[]'.
I’ve tried to solve it:
https://forums.xamarin.com/discussion/73169/uwp-10-build-fail-arrays-of-pointer-types-error
There is advice to remove the link to .dll, but I need it.
I’ve tried to install NAudio the same version using Manage NuGet Packages, but WaveFileReader, WaveFileWriter is not available.
In NAudio developer’s answer (How to store a .wav file in Windows 10 with NAudio) I’ve read about using AudioGraph, but I can build float array of samples only in the realtime playback, but I need get the full samples to pack right after the audio file uploading. Example of getting samples during the recording process or playback:
https://learn.microsoft.com/ru-ru/windows/uwp/audio-video-camera/audio-graphs
That’s why I need help: how to get FloatBuffer for working with samples after audio file uploading? For example, for building audio waves or calculation for audio effects applying.
Thank you in advance.
I’ve tried to use FileStream and BitConverter.ToSingle(), however, I had a different result compared to NAudio.
In other words, I’m still looking for a solution.
private float[] GetBufferArray()
{
string _path = ApplicationData.Current.LocalFolder.Path.ToString() + "/track_1.mp3";
FileStream _stream = new FileStream(_path, FileMode.Open);
BinaryReader _binaryReader = new BinaryReader(_stream);
int _dataSize = _binaryReader.ReadInt32();
byte[] _byteBuffer = _binaryReader.ReadBytes(_dataSize);
int _sizeFloat = sizeof(float);
float[] _floatBuffer = new float[_byteBuffer.Length / _sizeFloat];
for (int i = 0, j = 0; i < _byteBuffer.Length - _sizeFloat; i += _sizeFloat, j++)
{
_floatBuffer[j] = BitConverter.ToSingle(_byteBuffer, i);
}
return _floatBuffer;
}
Another way to read samples from an audio file in UWP is using AudioGraph API. It will work for all audio formats that Windows10 supports
Here is a sample code
namespace AudioGraphAPI_read_samples_from_file
{
// App opens a file using FileOpenPicker and reads samples into array of
// floats using AudioGragh API
// Declare COM interface to access AudioBuffer
[ComImport]
[Guid("5B0D3235-4DBA-4D44-865E-8F1D0E4FD04D")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
unsafe interface IMemoryBufferByteAccess
{
void GetBuffer(out byte* buffer, out uint capacity);
}
public sealed partial class MainPage : Page
{
StorageFile mediaFile;
AudioGraph audioGraph;
AudioFileInputNode fileInputNode;
AudioFrameOutputNode frameOutputNode;
/// <summary>
/// We are going to fill this array with audio samples
/// This app loads only one channel
/// </summary>
float[] audioData;
/// <summary>
/// Current position in audioData array for loading audio samples
/// </summary>
int audioDataCurrentPosition = 0;
public MainPage()
{
this.InitializeComponent();
}
private async void Open_Button_Click(object sender, RoutedEventArgs e)
{
// We ask user to pick an audio file
FileOpenPicker filePicker = new FileOpenPicker();
filePicker.SuggestedStartLocation = PickerLocationId.MusicLibrary;
filePicker.FileTypeFilter.Add(".mp3");
filePicker.FileTypeFilter.Add(".wav");
filePicker.FileTypeFilter.Add(".wma");
filePicker.FileTypeFilter.Add(".m4a");
filePicker.ViewMode = PickerViewMode.Thumbnail;
mediaFile = await filePicker.PickSingleFileAsync();
if (mediaFile == null)
{
return;
}
// We load samples from file
await LoadAudioFromFile(mediaFile);
// We wait 5 sec
await Task.Delay(5000);
if (audioData == null)
{
ShowMessage("Error loading samples");
return;
}
// After LoadAudioFromFile method finished we can use audioData
// For example we can find max amplitude
float max = audioData[0];
for (int i = 1; i < audioData.Length; i++)
if (Math.Abs(audioData[i]) > Math.Abs(max))
max = audioData[i];
ShowMessage("Maximum is " + max.ToString());
}
private async void ShowMessage(string Message)
{
var dialog = new MessageDialog(Message);
await dialog.ShowAsync();
}
private async Task LoadAudioFromFile(StorageFile file)
{
// We initialize an instance of AudioGraph
AudioGraphSettings settings =
new AudioGraphSettings(
Windows.Media.Render.AudioRenderCategory.Media
);
CreateAudioGraphResult result1 = await AudioGraph.CreateAsync(settings);
if (result1.Status != AudioGraphCreationStatus.Success)
{
ShowMessage("AudioGraph creation error: " + result1.Status.ToString());
}
audioGraph = result1.Graph;
if (audioGraph == null)
return;
// We initialize FileInputNode
CreateAudioFileInputNodeResult result2 =
await audioGraph.CreateFileInputNodeAsync(file);
if (result2.Status != AudioFileNodeCreationStatus.Success)
{
ShowMessage("FileInputNode creation error: " + result2.Status.ToString());
}
fileInputNode = result2.FileInputNode;
if (fileInputNode == null)
return;
// We read audio file encoding properties to pass them to FrameOutputNode creator
AudioEncodingProperties audioEncodingProperties = fileInputNode.EncodingProperties;
// We initialize FrameOutputNode and connect it to fileInputNode
frameOutputNode = audioGraph.CreateFrameOutputNode(audioEncodingProperties);
fileInputNode.AddOutgoingConnection(frameOutputNode);
// We add a handler achiving the end of a file
fileInputNode.FileCompleted += FileInput_FileCompleted;
// We add a handler which will transfer every audio frame into audioData
audioGraph.QuantumStarted += AudioGraph_QuantumStarted;
// We initialize audioData
int numOfSamples = (int)Math.Ceiling(
(decimal)0.0000001
* fileInputNode.Duration.Ticks
* fileInputNode.EncodingProperties.SampleRate
);
audioData = new float[numOfSamples];
audioDataCurrentPosition = 0;
// We start process which will read audio file frame by frame
// and will generated events QuantumStarted when a frame is in memory
audioGraph.Start();
}
private void FileInput_FileCompleted(AudioFileInputNode sender, object args)
{
audioGraph.Stop();
}
private void AudioGraph_QuantumStarted(AudioGraph sender, object args)
{
AudioFrame frame = frameOutputNode.GetFrame();
ProcessInputFrame(frame);
}
unsafe private void ProcessInputFrame(AudioFrame frame)
{
using (AudioBuffer buffer = frame.LockBuffer(AudioBufferAccessMode.Read))
using (IMemoryBufferReference reference = buffer.CreateReference())
{
// We get data from current buffer
((IMemoryBufferByteAccess)reference).GetBuffer(
out byte* dataInBytes,
out uint capacityInBytes
);
// We discard first frame; it's full of zeros because of latency
if (audioGraph.CompletedQuantumCount == 1) return;
float* dataInFloat = (float*)dataInBytes;
uint capacityInFloat = capacityInBytes / sizeof(float);
// Number of channels defines step between samples in buffer
uint step = fileInputNode.EncodingProperties.ChannelCount;
// We transfer audio samples from buffer into audioData
for (uint i = 0; i < capacityInFloat; i += step)
{
if (audioDataCurrentPosition < audioData.Length)
{
audioData[audioDataCurrentPosition] = dataInFloat[i];
audioDataCurrentPosition++;
}
}
}
}
}
}
Edited: It solves the problem because it reads samples from a file into a float array
First popular way of getting AudioData from Wav file.
Thanks to PI user’s answer How to read the data in a wav file to an array, I’ve solved the problem with wav file reading in float array in UWP project.
But file’s structure differs from standard one (maybe, only in my project there is such problem) when it records in wav file using AudioGraph. It leads to unpredictable result. We receive value1263424842 instead of predictable 544501094 getting format id. After that, all following values are displayed incorrectly. I’ve found out the correct id sequentially searching in the bytes. I realised that AudioGraph adds extra chunk of data to recorded wav file, but record’s format is still PCM. This extra chunk of data looks like the data about file format, but it contains also empty values, empty bytes. I can’t find any information about that, maybe somebody here knows? The solution from PI I’ve changed for my needs. That’s what I’ve got:
using (FileStream fs = File.Open(filename, FileMode.Open))
{
BinaryReader reader = new BinaryReader(fs);
int chunkID = reader.ReadInt32();
int fileSize = reader.ReadInt32();
int riffType = reader.ReadInt32();
int fmtID;
long _position = reader.BaseStream.Position;
while (_position != reader.BaseStream.Length-1)
{
reader.BaseStream.Position = _position;
int _fmtId = reader.ReadInt32();
if (_fmtId == 544501094) {
fmtID = _fmtId;
break;
}
_position++;
}
int fmtSize = reader.ReadInt32();
int fmtCode = reader.ReadInt16();
int channels = reader.ReadInt16();
int sampleRate = reader.ReadInt32();
int byteRate = reader.ReadInt32();
int fmtBlockAlign = reader.ReadInt16();
int bitDepth = reader.ReadInt16();
int fmtExtraSize;
if (fmtSize == 18)
{
fmtExtraSize = reader.ReadInt16();
reader.ReadBytes(fmtExtraSize);
}
int dataID = reader.ReadInt32();
int dataSize = reader.ReadInt32();
byte[] byteArray = reader.ReadBytes(dataSize);
int bytesForSamp = bitDepth / 8;
int samps = dataSize / bytesForSamp;
float[] asFloat = null;
switch (bitDepth)
{
case 16:
Int16[] asInt16 = new Int16[samps];
Buffer.BlockCopy(byteArray, 0, asInt16, 0, dataSize);
IEnumerable<float> tempInt16 =
from i in asInt16
select i / (float)Int16.MaxValue;
asFloat = tempInt16.ToArray();
break;
default:
return false;
}
//For one channel wav audio
floatLeftBuffer.AddRange(asFloat);
From buffer to file record has inverse algorithm. At this moment this is the only one correct algorithm for working with wav files which allows to get audio data.
Used this article working with AudioGraph - https://learn.microsoft.com/ru-ru/windows/uwp/audio-video-camera/audio-graphs. Note that you can set up necessary data of record’s format with AudioEncodingQuality recirdung from MIC to file.
Second way of getting AudioData using NAudio from Nugget Packages.
I used MediaFoundationReader class.
float[] floatBuffer;
using (MediaFoundationReader media = new MediaFoundationReader(path))
{
int _byteBuffer32_length = (int)media.Length * 2;
int _floatBuffer_length = _byteBuffer32_length / sizeof(float);
IWaveProvider stream32 = new Wave16ToFloatProvider(media);
WaveBuffer _waveBuffer = new WaveBuffer(_byteBuffer32_length);
stream32.Read(_waveBuffer, 0, (int)_byteBuffer32_length);
floatBuffer = new float[_floatBuffer_length];
for (int i = 0; i < _floatBuffer_length; i++) {
floatBuffer[i] = _waveBuffer.FloatBuffer[i];
}
}
Comparing two ways I noticed:
Received values of samples differ on 1/1 000 000. I can’t say what way is more precise (if you know, will be glad to hear);
Second way of getting AudioData works for MP3 files, too.
If you’ve found any mistakes or have comments about that, welcome.
Import statement
using NAudio.Wave;
using NAudio.Wave.SampleProviders;
Inside function
AudioFileReader reader = new AudioFileReader(filename);
ISampleProvider isp = reader.ToSampleProvider();
float[] buffer = new float[reader.Length / 2];
isp.Read(buffer, 0, buffer.Length);
buffer array will be having 32 bit IEEE float samples.
This is using NAudio Nuget Package Visual Studio.
I want to do some changing on Wave file, then Play it Directly after doing that.
So I define a byte array to store the bytes of wave file on it as following:
byte[] byteArr;
byteArr = File.ReadAllBytes(dlg.FileName);
where dlg is an OpenFile Dialog.
Then I do a changing to sample bit rate of wave as following:
private void playSlectedWave_Click(object sender, EventArgs e)
{
int sample = 50000;
MemoryStream fs = new MemoryStream(byteArr);
BinaryReader br = new BinaryReader(fs);
int length = (int)fs.Length-8;
fs.Position = 22;
short channels = br.ReadInt16();
fs.Position = 34;
short BitsPerSample = br.ReadInt16();
byte[] arrfile = new byte[fs.Length];
fs.Position = 0;
fs.Read(arrfile, 0, arrfile.Length);
BinaryWriter bw = new BinaryWriter(fs);
bw.BaseStream.Seek(0, SeekOrigin.Begin);
bw.Write(arrfile, 0, 24);
bw.Write(sample);
bw.Write((int)(sample* ((BitsPerSample * channels) / 8)));
bw.Write((short)((BitsPerSample * channels) / 8));
bw.Write(arrfile, 34, arrfile.Length - 34);
SoundPlayer SP = new SoundPlayer(fs);
SP.Play();
}
My question is that when it reaches the SP.Play() it throws an exception that says that the Wave Header is corrupted.
For more Information, I try the previous code but with FileStream instead of MemoryStream and it works fine for me .
Does Anyone know why?
Define your SoundPlayer SP outside of your sub/function or use
SP.PlaySync
SP.Play();
Is Async, after hitting that line you leave the Sub while it is still playing in the background and the memorystream is likely modified or removed from memory.
You are lucky that you only get an exception, there is a possibility that your program would just crash even when debugging without any exception.
Try:
SP.Stream.Position = 0;
It was a solution at least for my situation.
Format your desired audio file correctly to a .wav file!
I thought this would work:
soundPlayer.Stream.Position = 0;
But sadly, it compiled to no avail...
Try this site to format: http://audio.online-convert.com/convert-to-wav
I want to calculate download speed as kbps (kb per second). There's a problem in the code, it doesn't show actual speed. And I'm really tired of this work. Also, when using (TotalDownloadSize / ElapsedTime) formula it shows more realistic results but you know it will get average value and it will be stupidity.
It usually gives 4000 and it's basicly because of chunk 4096 when I set it to 128 that time I get 50/100/125 values.
DateTime dlElapsed;
private delegate void UpdateProgessCallback(Int64 BytesRead, Int64 TotalBytes, Int32 CurrentBytes);
private void UpdateProgress(Int64 BytesRead, Int64 TotalBytes, Int32 CurrentBytes)
{
DateTime Elapsed = DateTime.Now;
var progress = Convert.ToInt32((BytesRead * 100) / TotalBytes);
var elaps = (Elapsed - dlElapsed).TotalSeconds;
long kbps;
if (elaps > 0)
{
kbps = Convert.ToInt64((CurrentBytes / elaps) / 1024);
updateLabelText(String.Format("Downloading ({0} kbps)...", kbps));
}
// Make progress on the progress bar
if (progress < progressBar1.Maximum)
{
progressBar1.Value = progress;
}
else
{
progressBar1.Value = progressBar1.Maximum;
}
dlElapsed = DateTime.Now;
}
private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
// Some stuff here...
int byteSize = 0;
byte[] downBuffer = new byte[4096];
FileStream strLocal= new FileStream(path, FileMode.Create, FileAccess.Write);
dlElapsed = DateTime.Now;
while ((byteSize = stream.Read(downBuffer, 0, downBuffer.Length)) > 0)
{
strLocal.Write(downBuffer, 0, byteSize);
this.Invoke(new UpdateProgessCallback(this.UpdateProgress),
new object[] { strLocal.Length, totalbyte, byteSize});
}
updateLabelText("Download complete!");
strLocal.Close();
}
}
So where's the problem?
So where's the problem?
You're coarsely sampling something that varies a lot.
Consider buffering measurements and averaging the last 5 or so. Look for implementations of a "running average".
Well, my first comment would be that your code is not thread safe, so when you set dlElapsed = DateTime.Now;, it's not the same dlElapsed value that UpdateProgress is going to be checking.
I want to create a huge dummy file say 1~2 GBs in matter of seconds.
here is what I've written in C#:
file.writeallbytes("filename",new byte[a huge number]);
and another way with indicating the status, was like following:
long FSS = din.TotalFreeSpace;
long segments = FSS / 10000;
long last_seg = FSS % 10000;
BinaryWriter br = new BinaryWriter(fs);
for (long i = 0; i < segments; i++)
{
br.Write(new byte[10000]);
this.label2.Text = "segments write :" + i.ToString() + "\r\n" + "segments remain :" + ((segments-i)+1).ToString();
Application.DoEvents();
}
br.Write(new byte[last_seg]);
this.label2.Text += "\r\nDone!";
br.Close();
where din is Disk Information object
well with these two approach it takes something like 2 or more minutes to write such a big but dummy file. Is there any other faster way for doing so?
Simply create the file, seek to a suitably large offset, and write a single byte:
FileStream fs = new FileStream(#"c:\tmp\huge_dummy_file", FileMode.CreateNew);
fs.Seek(2048L * 1024 * 1024, SeekOrigin.Begin);
fs.WriteByte(0);
fs.Close();
This will yield a 2GB file with basically unpredictable contents, which should be fine for your purposes.
If you don't care about the contents, then by far the fastest way I know of is this - it is practically instant:
private void CreateDummyFile(string fileName, long length)
{
using (var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
{
fileStream.SetLength(length);
}
}
If you just need a FileStream, you could use FileStream.SetLength. That will get you a stream which is 2 GB long. Then you can write the final byte at an arbitrary position of your choice. But the contents will be undefined.
If you're trying to actually create a file on the disk, yes, you'll need to actually write its contents. And yes, hard disks are going to be slow; something like a 1 GB/min write speed isn't totally ridiculous. Sorry -- that's physics!
Why did you not use the BackgroundWorker class to achieve this, as you can pass anything into the method ReportProgress to indicate the status report. See the example below:
private BackgroundWorker bgWorker;
public Form1()
{
InitializeComponent();
bgWorker = new BackgroundWorker();
bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged);
bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
bgWorker.RunWorkerAsync();
}
void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.label2.Text = "Done";
}
void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
MyStatus myProgressStatus = (MyStatus)e.UserState;
this.label2.Text = string.Format("segments write : {0}" + Environment.Newline + "Segments Remain: {1}", myProgressStatus.iWritten, myProgressStatus.iRemaining);
}
void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
long FSS = din.TotalFreeSpace;
long segments = FSS / 10000;
long last_seg = FSS % 10000;
BinaryWriter br = new BinaryWriter(fs);
for (long i = 0; i < segments; i++)
{
br.Write(new byte[10000]);
bgWorker.ReportProgress(i.ToString(), new MyStatus(i, ((segments-i) + 1)));
}
br.Write(new byte[last_seg]);
br.Close();
}
public class MyStatus{
public int iWritten;
public int iRemaining;
public MyStatus(int iWrit, int iRem){
this.iWritten = iWrit;
this.iRemaining = iRem;
}
}
}
This is a rough draft...
I could be wrong but you will probably find that it's impossible to create a file that large that quickly as there will be a bottleneck in the I/O writing process.
However in your code above the Applciation.DoEvents will be slowing things down. Also any repainting of the screenthis.label2.Text = will cause a slight slow down.