How do I read a file in parts with NAudio? - c#

I am fairly new to C# and Mark's library NAudio. So I've tried learning by myself and I've come up with an basic audio player. But I have a problem.
When trying to load big files in the player the app freezes for 2-10 seconds while loading the entire file (I suppose). This is my code for reading the file:
if (target.EndsWith("mp3") || target.EndsWith("Mp3") || target.EndsWith("MP3"))
{
NAudio.Wave.WaveStream pcm = NAudio.Wave.WaveFormatConversionStream.CreatePcmStream(new NAudio.Wave.Mp3FileReader(target));
stream = new NAudio.Wave.BlockAlignReductionStream(pcm);
}
All I really want is to read the file in parts. Like a buffer. Read 10 seconds from the HDD to RAM memory, then after those 10 seconds run out, read the next 10 seconds, and so on. I think this should resolve the freeze issue I have with large files.

The cause of the delay is that Mp3FileReader creates a table of contents to allow it to determine the file length and to enable quicker repositioning. You could try using MediaFoundationReader instead which would be quicker, but won't work on Windows XP.

all programs have delay to load big files. this is depended to client computer speed.
but you can use backgroundWorker in your program and show a loading animation on your application Form during the file loading.
add backgroundWorker tool on your form
use this code on open button click:
backgroundWorker_name.RunWorkerAsync();
and put your code to the DoWork event
private void backgroundWorker_name_DoWork(object sender, DoWorkEventArgs e)
{
}

Related

CefSharp detect webm video end

I have a WPF C# application using cefsharp v79.1.360.
The app is happily playing a single local webm file inside the browser.
Now I would like to pass a string of local file names to the app and play them sequentially. Thus when one webm finishes playing the next one in sequence will start. Nothing else is contained in the page, just the webm.
My first thought was to detect when the current webm finishes and then load the next file. I am not seeing any events being thrown or handlers that can do this for me.
I am using the FrameLoadEnd handler for other purposes but it only fires when the webm has finished loading, not when it is done playing.
Anyone know if detecting the ending of a webm video is possible?
My other thought is to load each webm into a stream and play the entire batch.
For user experience purposes I think it would be better to play each one individually, in sequence.
Thanks
Decided the best way to solve the problem was to create an html page that would accept a delimited string of video locations. It handles cycling through the list, playing each one individually. All it had to do was change the src of the video tag when the onended event fired and when the loadPlaylist function below is called.
The C# app passed the playlist to the html via a javascript call:
Browser.FrameLoadEnd += (sender, args) =>
{
//Wait for the Main Frame to finish loading
if (args.Frame.IsMain)
{
var playlist = navigationContext.Parameters[NavigationParameterKeys.WebAddress].ToString();
args.Frame.ExecuteJavaScriptAsync("loadPlaylist('" + playlist +"');");
}
};

Is there a way to make multiple running threads pulling data from a stream start writing that data to separate files at the exact same time?

I'm writing softare that records data from a number of sensors. A user should be able to press a button to start streaming and then another to start recording this data to a file. Each device has its own thread so pressing the stream button will start a thread to stream for each device, and pressing record should make all these threads start writing to files.
I've attempted to implement this by creating a new thread to start pulling samples and then using a volatile bool to tell the threads when to start writing the samples to a file.
Here is the code running inside the threads:
public void streamData(CancellationToken ct, liblsl.StreamInlet inlet)
{
while (true)
{
ct.ThrowIfCancellationRequested();
pullSampleFromLSL(inlet);
//start writing to file if requested
//if(_isRecording){
// writeToFile()
//}
}
}
This method hasn't provided the accuracy I was hoping for as each file records a different timestamp for when recording was started (recorded using Stopwatch.ElapsedMilliseconds from a set starting point). Is there a way to do this so that all the files begin at (as close to as possible) the exact same timestamp?
cheers
Actually I would use a monitor class that trought condition variables notify all thread to start.

c# ThreadPool using less threads than cores because of memory restrictions with FileSystemWatcher

I have an extensive image calculation task which uses about 1GB of memory (one calculation cycle takes about 4 seconds). I process those images automatically when they arrive in the folder using a FileSystemWatcher. When the FileSystemWatcher fires an event for a new file I queue the work in the eventhandler method with:
private void OnNewFileInDir(object source, FileSystemEventArgs evtArgs)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessTheNewImage), evtArgs.FullPath);
}
My problem is that the program crashes on a regular basis when the files arrive quickly. In the debug window I can see that neary 3GB memory are used in that moment. When I use smaller images in order to use less memory, there are no crashes (so far).
My question: What can I do to use less (maybe just 2) threads independent of cores of my computer?
Or is my approach of using a FileSystemWatcher to cue new files to a thread pool completely stupid? I am not at all experienced with thread races or similar things.
So, furthermore: Does that look threadsafe?
Thanks a lot upfront and all the best
Tim
For completeness here is the code executed by the threads (a bit simplified for ease of reading):
private void ProcessTheNewImage(object threadFilenameInfo)
{
String filename = (String)threadFilenameInfo;
// Load the image
Image currentImage = Image.FromFile(filename);
//Calculate the image in an external DLL
Image currentResultImage = ImageProcessing.getResultImage(currentImage);
//Create the filename with the result infos
string saveFileName = "blahblah";
//Save the image
currentResultImage.Save(saveFileName);
//dispose the images
currentImage.Dispose();
currentResultImage.Dispose();
}
The Threadpool has only a very limited form of resource management. It will slowly keep adding threads when the queue fills up. It is meant for relatively small (< 500 ms) jobs. There is no safety-valve to stop it from clogging up your application.
You could create a workflow for this: the watcher event pushes simple datapackets into a ConcurrentQueue and then you create 2 or more Threads (better: Tasks) to process the queue. This will allow you to tune the number of threads.

OutOfMemoryException # WriteableBitmap # background agent

I have a Windows Phone 8 App, which uses Background agent to:
Get data from internet;
Generate image based on a User Control that uses the data from step 1 as data source;
In the User Control I have Grid & StackPanel & some Text and Image controls;
When some of the Images use local resources from the installation folder (/Assets/images/...)
One of them which I used as a background is selected by user from the phone's photo library, so I have to set the source using C# code behind.
However, when it runs under the background, it get the OutOfMemoryException, some troubleshooting so far:
When I run the process in the "front", everything works fine;
If I comment out the update progress, and create the image directly, it also works fine;
If I don't set the background image, it also works fine;
The OutOfMemoryException was thrown out during var bmp = new WriteableBitmap(480, 800);
I already shrink the image size from 1280*768 to 800*480, I think it is the bottom line for a full screen background image, isn't it?
After some research, I found out this problem occurs because it exceeded the 11 MB limitation for a Periodic Task.
I tried use the DeviceStatus.ApplicationCurrentMemoryUsage to track the memory usageļ¼š
-- the limitation is 11,534,336 (bit)
-- when background agent started, even without any task in it, the memory usage turns to be 4,648,960
-- When get update from internet, it grew up to 5,079,040
-- when finished, it dropped back to 4,648,960
-- When the invoke started (to generate image from the User Control), it grew up to 8,499,200
Well, I guess that's the problem, there is little memory available for it to render the image via WriteableBitmap.
Any idea how to work out this problem?
Is there a better method to generate an image from a User Control / or anything else?
Actually the original image might only be 100 kb or around, however, when rendering by WriteableBitmap, the file size (as well as the required memory size I guess) might grew up to 1-2MB.
Or can I release the memory from anywhere?
==============================================================
BTW, when this Code Project article says I can use only 11MB memory in a Periodic Task;
However, this MSDN article says that I can use up to 20 MB or 25MB with Windows Phone 8 Update 3;
Which is correct? And why am I in the first situation?
==============================================================
Edit:
Speak of the debugger, it also stated in the MSDN article:
When running under the debugger, memory and timeout restrictions are suspended.
But why would I still hit the limitation?
==============================================================
Edit:
Well, I found something seems to be helpful, I will check on them for now, suggestions are still welcome.
http://writeablebitmapex.codeplex.com/
http://suchan.cz/2012/07/pro-live-tiles-for-windows-phone/
http://notebookheavy.com/2011/12/06/microsoft-style-dynamic-tiles-for-windows-phone-mango/
==============================================================
The code to generate the image:
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
var customBG = new ImageUserControl();
customBG.Measure(new Size(480, 800));
var bmp = new WriteableBitmap(480, 800); //Thrown the **OutOfMemoryException**
bmp.Render(customBG, null);
bmp.Invalidate();
using (var isf = IsolatedStorageFile.GetUserStoreForApplication())
{
filename = "/Shared/NewBackGround.jpg";
using (var stream = isf.OpenFile(filename, System.IO.FileMode.OpenOrCreate))
{
bmp.SaveJpeg(stream, 480, 800, 0, 100);
}
}
}
The XAML code for the ImageUserControl:
<UserControl blabla... d:DesignHeight="800" d:DesignWidth="480">
<Grid x:Name="LayoutRoot">
<Image x:Name="nBackgroundSource" Stretch="UniformToFill"/>
//blabla...
</Grid>
</UserControl>
The C# code behind the ImageUserControl:
public ImageUserControl()
{
InitializeComponent();
LupdateUI();
}
public void LupdateUI()
{
DataInfo _dataInfo = new DataInfo();
LayoutRoot.DataContext = _dataInfo;
try
{
using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication())
{
using (var isoFileStream = isoStore.OpenFile("/Shared/BackgroundImage.jpg", FileMode.Open, FileAccess.Read))
{
BitmapImage bi = new BitmapImage();
bi.SetSource(isoFileStream);
nBackgroundSource.Source = bi;
}
}
}
catch (Exception) { }
}
When DataInfo is another Class within the settings page that hold data get from the internet:
public class DataInfo
{
public string Wind1 { get { return GetValueOrDefault<string>("Wind1", "N/A"); } set { if (AddOrUpdateValue("Wind1", value)) { Save(); } } }
public string Wind2 { get { return GetValueOrDefault<string>("Wind2", "N/A"); } set { if (AddOrUpdateValue("Wind2", value)) { Save(); } } }
//blabla...
}
If I comment out the update progress, and create the image directly, it also works fine I think you should focus on that part. It seems to indicate some memory isn't freed after the update. Make sure all the references used during the update process go out of scope before rendering the picture. Forcing a garbage collection can help too:
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect(); // Frees the memory that was used by the finalizers
Another thing to consider is that the debugger is also using a lot of memory. Do a real test by compiling your project in "Release" mode and deploying on a phone to make sure you're running out of memory.
Still, I have already been in that situation so I know it may not be enough. The point is: some libraries in the .NET Framework are loaded lazily. For instance, if your update process involves downloading some data, then the background agent will load the network libraries. Those libraries can't be unloaded and will waste some of your agent's memory. That's why, even by freeing all the memory you used during the update process, you won't reach back the same amount of free memory you had when starting the background agent. Seeing this, what I did in one of my app was to span the workload of the background agent across two executions. Basically, when the agents executes:
Check in the isolated storage if there's pending data to be processed. If not, just execute the update process and store all needed data in the isolated storage
If there is pending data (that is, in the next execution), generate the picture and clear the data
It means the picture will be generated only once every hour instead of once every 30 minutes, so use this workaround only if everything else fail.
The larger memory limit is for background audio agents, it clearly states that in the documentation. You're stuck with 11 MB, which can really be a big pain when you're trying to do something smart with pictures in the background.
480x800 adds a MB to your memory because it takes 4 bytes for every pixels, so in the end it's around 1.22MB. When compressed in JPEG, then yes - it makes sense that it's only around 100KB. But whenever you use WriteableBitmap, it gets loaded into memory.
One of the things you could try before forcing the GC.Collect as mentioned in another answer is to null things out even before they go out of scope - whether it's a BitmapImage or a WriteableBitmap. Other than that you can try removing the Image object from the Grid programmatically when you're done and setting the Source of it also to be null.
Are there any other WriteableBitmap, BitmapImage or Image objects you're not showing us?
Also, try without the debugger. I've read somewhere that it adds another 1-2MB which is a lot when you have only 11 MB. Although, if it crashes so quickly with the debugger, I wouldn't risk it even if it suddenly seams OK without the debugger. But just for testing purposes you can give it a shot.
Do you need to use the ImageUserControl? Can you try doing step by step creating Image and all the other objects, without the XAML, so you can measure memory in each and every step to see at which point it goes through the roof?

Fastest way to send keystrokes C#

I was wondering what the fastest way to send keystrokes using C# is. Currently I am using SendKeys.Send() and SendKeys.SendWait() with SendKeys.Flush().
I am using the following code to calculate the time of how long it takes for the both of them to work:
Stopwatch sw1 = new Stopwatch();
sw1.Start();
for (int a = 1; a <= 1000; a++)
{
SendKeys.Send("a");
SendKeys.Send("{ENTER}");
}
sw1.Stop();
And:
Stopwatch sw2 = new Stopwatch();
sw2.Start();
for (int b = 1; b <= 1000; b++)
{
SendKeys.SendWait("b");
SendKeys.SendWait("{ENTER}");
SendKeys.Flush();
}
sw2.Stop();
The results of the 2 are:
Result 1: 40119 milliseconds
Result 2: 41882 milliseconds
Now if we put the SendKeys.Flush() on the second test, outside of the loop we get:
Result 3: 46278 milliseconds
I was wondering why these changes in the code make the speed very different.
I was also wondering if there is a faster way of sending many keystrokes, as my application does it a lot. (These tests were done on a really slow netbook)
Thanks!
SendWait() is slower because it waits that the message has been processed by the target application. The Send() function instead doesn't wait and returns as soon as possible. If the application is somehow busy the difference can be even much more evident.
If you call Flush() you'll stop your application to process all events related to the keyboard that are queued in the message queue. It doesn't make too much sense if you sent them using SendWait() and you'll slow down a lot the application because it's inside the loop (imagine Flush() as a selective DoEvents() - yes with all its drawbacks - and it's called by SendWait() itself too).
If you're interested about its performance (but they'll always be limited to the speed at which your application can process the messages) please read this on MSDN. In sum, you can change the SendKeys class to use the SendInput function, rather than a journal hook. As quick reference, simply add this setting to your app.config file:
<appSettings>
<add key="SendKeys" value="SendInput"/>
</appSettings>
Anyway, the goal of the new implementation isn't the speed but consistent behavior across different versions of Windows and and options (the increased performance is kind of a side effect, I guess).
If you have a lot of text to push to a client, you may notice that SendKeys is really sluggish. You can vastly speed things up by using the clipboard. The idea is to put the text you wish to "type" into a target text box in the clipboard and then send a CTRL-V to the target application to paste that text. Here's an illustration:
Clipboard.Clear(); // Always clear the clipboard first
Clipboard.SetText(TextToSend);
SendKeys.SendWait("^v"); // Paste
I found this worked well for me with a cordless bar code scanner that talks via WiFi to a host app that sends long bar codes to a web app running in Google Chrome. It went from tediously pecking out 30 digits over about 4 seconds to instantly pasting all in under a second.
One obvious downside is that this can mess with your user's use of the clipboard. Another is that it doesn't help if you intend to send control codes like TAB or F5 instead of just plain old text.

Categories