Song class not working properly - silverlight

In my silverlight WP7 app, I am using XNA library to play sound. Following is the code.
Microsoft.Xna.Framework.Media.Song s = Microsoft.Xna.Framework.Media.Song.FromUri("song", new Uri("bmusic.mp3", UriKind.Relative));
Microsoft.Xna.Framework.FrameworkDispatcher.Update();
Microsoft.Xna.Framework.Media.MediaPlayer.IsRepeating = true;
Microsoft.Xna.Framework.Media.MediaPlayer.Play(s);
It starts playing the sound and stops after a second, while the song is 10 secs long. What is wrong ?

Silverlight is event based, whereas XNA is more loop based. You need to enable XNA framework events, as explained here. As a quick test to see if that is the issue, in your page's constructor, you can add this:
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(30);
timer.Tick += delegate { try { FrameworkDispatcher.Update(); } catch { } };
timer.Start();

Related

Simple DispatchTimer Ticks are erratic WPF in Win10 only

I have tried this on Win7 and Win10. On Win7 works as I thought, Tick is called every 100ms. But on win10, the Tick is called 2 times at run, and then stops until I do a mouseover the app, which fires anouther Tick for 1 time. This is weird.
I'm using System.Windows.Threading.
The code is all in code-behind to test it and this is all to keep it simple:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
TimerGeneral(true);
}
public DispatcherTimer timer = new DispatcherTimer();
int s;
public void TimerGeneral(bool estado)
{
timer.Interval = TimeSpan.FromMilliseconds(100);
if (estado && !timer.IsEnabled) { timer.Tick += timer_Tick; timer.Start(); }
else if (!estado && timer.IsEnabled) { timer.Stop(); }
}
public void timer_Tick(object sender, EventArgs e)
{
Debug.WriteLine("tick" + s++);
}
}
I'm a little lost why Win10 works different, sorry.
Keep in mind, that when instantiating DispatcherTimer using the default constructor (as you did), the timer's Dispatcher will by default execute with DispatcherPriority.Background! Hence the high latency.
Specify a higher priority by using the appropriate constructor:
var dispatcherTimer = new DispatcherTimer(DispatcherPriority.Normal, Application.Current.Dispatcher)
This should fix your issue.
In case the latency is still too high, try DispatcherPriority.Send (use with care).
If an operation is posted to a Dispatcher at DispatcherPriority.Send, the operation bypasses the queue and is immediately executed.
Depending on the timer interval and workload, the DispatcherPriority should be as low as possible to prevent the UI from becoming sluggish.
Alternatively, if Timers.Timer or any other timer is working better for you, then just use it. You can execute the UI relevant code using Application.Current.Dispatcher.Invoke(Action) or Application.Current.Dispatcher.InvokeAsync(Action).

System.Windows.Controls.WebBrowser, System.Windows.Threading.Dispatcher, and a windows service

I'm trying to render some html content to a bitmap in a Windows Service.
I'm using System.Windows.Controls.WebBrowser to perform the render. The basic rendering setup works as a standalone process with a WPF window hosting the control, but as a service, at least I'm not getting the LoadCompleted events to fire.
I know that I at least need a Dispatcher or other message pump looping for this WPF control. Perhaps I'm doing it right and there are just additional tricks/incompatibilities necessary for the WebBrowser control. Here's what I've got:
I believe only one Dispatcher needs to be running and that it can run for the life of the service. I believe the Dispatcher.Run() is the actual loop itself and thus needs it's own thread which it can otherwise block. And that thread needs to be [STAThread] in this scenario. Therefore, in a relevant static constructor, I have the following:
var thread = new Thread(() =>
{
dispatcher = Dispatcher.CurrentDispatcher;
Dispatcher.Run();
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
where dispatcher is a static field. Again, I think there can only be one but I'm not sure if I'm supposed to be able use Dispatcher.CurrentDispatcher() from anywhere instead and get the right reference.
The rendering operation is as follows. I create, navigate, and dispose of the WebBrowser on dispatcher's thread, but event handler assignments and mres.Wait I think may all happen on the render request-handling operation. I had gotten The calling thread cannot access this object because a different thread owns it but now with this setup I don't.
WebBrowser wb = null;
var mres = new ManualResetEventSlim();
try
{
dispatcher.Invoke(() => { wb = new WebBrowser(); });
wb.LoadCompleted += (s, e) =>
{
// Not firing
};
try
{
using (var ms = new MemoryStream())
using (var sw = new StreamWriter(ms, Encoding.Unicode))
{
sw.Write(html);
sw.Flush();
ms.Seek(0, SeekOrigin.Begin);
// GO!
dispatcher.Invoke(() =>
{
try
{
wb.NavigateToStream(ms);
Debug.Assert(Dispatcher.FromThread(Thread.CurrentThread) != null);
}
catch (Exception ex)
{
// log
}
});
if (!mres.Wait(15 * 1000)) throw new TimeoutException();
}
}
catch (Exception ex)
{
// log
}
}
finally
{
dispatcher.Invoke(() => { if (wb != null) wb.Dispose(); });
}
When I run this, I get my timeout exception every time since the LoadCompleted never fires. I've tried to verify that the dispatcher is running and pumping properly. Not sure how to do that, but I hooked a few of the dispatcher's events from the static constructor and I get some printouts from that, so I think it's working.
The code does get to a wb.NavigateToStream(ms); breakpoint.
Is this bad application of Dispatcher? Is the non-firing of wb.LoadCompleted due to something else?
Thanks!
Here's a modified version of your code which works as a console app. A few points:
You need a parent window for WPF WebBrowser. It may be a hidden window like below, but it has to be physically created (i.e. have a live HWND handle). Otherwise, WB never finishes loading the document (wb.Document.readyState == "interactive"), and LoadCompleted never gets fired. I was not aware of such behavior and it is different from the WinForms version of WebBrowser control. May I ask why you picked WPF for this kind of project?
You do need to add the wb.LoadCompleted event handler on the same thread the WB control was created (the dispatcher's thread here). Internally, WPF WebBrowser is just a wrapper around apartment-threaded WebBrowser ActiveX control, which exposes its events via IConnectionPointContainer interface. The rule is, all calls to an apartment-threaded COM object must be made on (or proxied to) the thread the object was originally created on, because that's what such kind of objects expect. In that sense, IConnectionPointContainer methods are no different to other methods of WB.
A minor one, StreamWriter automatically closes the stream it's initialized with (unless explicitly told to not do so in the constructor), so there is no need to for wrapping the stream with using.
The code is ready to compile and run (it requires some extra assembly references: PresentationFramework, WindowsBase, System.Windows, System.Windows.Forms, Microsoft.mshtml).
using System;
using System.Text;
using System.Threading;
using System.Diagnostics;
using System.Windows;
using System.Windows.Threading;
using System.Windows.Controls;
using System.IO;
using System.Runtime.InteropServices;
using mshtml;
namespace ConsoleWpfApp
{
class Program
{
static Dispatcher dispatcher = null;
static ManualResetEventSlim dispatcherReady = new ManualResetEventSlim();
static void StartUIThread()
{
var thread = new Thread(() =>
{
Debug.Print("UI Thread: {0}", Thread.CurrentThread.ManagedThreadId);
try
{
dispatcher = Dispatcher.CurrentDispatcher;
dispatcherReady.Set();
Dispatcher.Run();
}
catch (Exception ex)
{
Debug.Print("UI Thread exception: {0}", ex.ToString());
}
Debug.Print("UI Thread exits");
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
static void DoWork()
{
Debug.Print("Worker Thread: {0}", Thread.CurrentThread.ManagedThreadId);
dispatcherReady.Wait(); // wait for the UI tread to initialize
var mres = new ManualResetEventSlim();
WebBrowser wb = null;
Window window = null;
try
{
var ms = new MemoryStream();
using (var sw = new StreamWriter(ms, Encoding.Unicode)) // StreamWriter automatically closes the steam
{
sw.Write("<b>Hello, World!</b>");
sw.Flush();
ms.Seek(0, SeekOrigin.Begin);
// GO!
dispatcher.Invoke(() => // could do InvokeAsync here as then we wait anyway
{
Debug.Print("Invoke Thread: {0}", Thread.CurrentThread.ManagedThreadId);
// create a hidden window with WB
window = new Window()
{
Width = 0,
Height = 0,
Visibility = System.Windows.Visibility.Hidden,
WindowStyle = WindowStyle.None,
ShowInTaskbar = false,
ShowActivated = false
};
window.Content = wb = new WebBrowser();
window.Show();
// navigate
wb.LoadCompleted += (s, e) =>
{
Debug.Print("wb.LoadCompleted fired;");
mres.Set(); // singal to the Worker thread
};
wb.NavigateToStream(ms);
});
// wait for LoadCompleted
if (!mres.Wait(5 * 1000))
throw new TimeoutException();
dispatcher.Invoke(() =>
{
// Show the HTML
Console.WriteLine(((HTMLDocument)wb.Document).documentElement.outerHTML);
});
}
}
catch (Exception ex)
{
Debug.Print(ex.ToString());
}
finally
{
dispatcher.Invoke(() =>
{
if (window != null)
window.Close();
if (wb != null)
wb.Dispose();
});
}
}
static void Main(string[] args)
{
StartUIThread();
DoWork();
dispatcher.InvokeShutdown(); // shutdown UI thread
Console.WriteLine("Work done, hit enter to exit");
Console.ReadLine();
}
}
}
Maybe the Webbrowser Control needs Desktop Interaction for rendering the content:
My feeling say that using WPF controls and in particular particulary the Webbrowser-Control (=Wrapper around the IE ActiveX control) isn't the best idea.. There are other rendering engines that might be better suited for this task: Use chrome as browser in C#?

Idle time using DispatcherTimer - Not Working

I have an application all done in WPF, using MvvM/Prism/Unity and Remote as datasource.
I need a basic thing that on win forms is really easy, just check if the app is iddle after few minutes , and if is idle, lock the app and show the login screen.
After some search on google I ´ve found one solution that uses DllImport and another using pure Wpf methods.
I don´t know I , after I implemented the Wpf way (pls check the code below) it only works after I login into the app , if I open and click in a simple texbox or hit a search, the idle method is not fired, looks like there is something hanged in the background that makes Wpf idle routine to think that it´s doing something when it´s not.
How can I check all the services/methods/etc.. that are in memory related to may app ? callstack doesn´t show to much for me. I am affraid that or I am not calling in the correct way the remote services or I implemented something wrong on the props PropChanged events/observablecollections/etc...
Is there a better way to do this using 100% Wpf structure ?
private void CheckIdleTime()
{
handler = delegate
{
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(5);
timer.Tick += delegate
{
if (timer != null)
{
timer.Stop();
timer = null;
System.Windows.Interop.ComponentDispatcher.ThreadIdle -= handler;
Console.WriteLine("IDLE! Lets logoff!");
this.LockApplication();
Console.WriteLine("logoff fired");
System.Windows.Interop.ComponentDispatcher.ThreadIdle += handler;
}
};
timer.Start();
Dispatcher.CurrentDispatcher.Hooks.OperationPosted += delegate
{
if (timer != null)
{
timer.Stop();
timer = null;
}
};
};
ComponentDispatcher.ThreadIdle += handler;
}
There will be default window events find the idle time... i think it will be wise if we use same events for wpf or any other applications...
following link will help you to implement it..
Application.Idle event not firing in WPF application

Loading an image in a background thread in WPF

There are a bunch of questions about this already on this site and other forums, but I've yet to find a solution that actually works.
Here's what I want to do:
In my WPF app, I want to load an image.
The image is from an arbitrary URI on the web.
The image could be in any format.
If I load the same image more than once, I want to use the standard windows internet cache.
Image loading and decoding should happen synchronously, but not on the UI Thread.
In the end I should end up with something that I can apply to an <Image>'s source property.
Things I have tried:
Using WebClient.OpenRead() on a BackgroundWorker. Works fine, but doesn't use the cache. WebClient.CachePolicy only affects that particular WebClient instance.
Using WebRequest on the Backgroundworker instead of WebClient, and setting WebRequest.DefaultCachePolicy. This uses the cache properly, but I've not seen an example that doesn't give me corrupted-looking images half the time.
Creating a BitmapImage in a BackgroundWorker, setting BitmapImage.UriSource and trying to handle BitmapImage.DownloadCompleted. This seems to use the cache if BitmapImage.CacheOption is set, but there doesn't seem to be away to handle DownloadCompleted since the BackgroundWorker returns immediately.
I've been struggling with this off-and-on for literally months and I'm starting to think it's impossible, but you're probably smarter than me. What do you think?
I have approached this problem in several ways, including with WebClient and just with BitmapImage.
EDIT: Original suggestion was to use the BitmapImage(Uri, RequestCachePolicy) constructor, but I realized my project where I tested this method was only using local files, not web. Changing guidance to use my other tested web technique.
You should run the download and decoding on a background thread because during loading, whether synchronous or after download the image, there is a small but significant time required to decode the image. If you are loading many images, this can cause the UI thread to stall. (There are a few other intricacies here like DelayCreation but they don't apply to your question.)
There are a couple ways to load an image, but I've found for loading from the web in a BackgroundWorker, you'll need to download the data yourself using WebClient or a similar class.
Note that BitmapImage internally uses a WebClient, plus it has a lot of error handling and settings of credentials and other things that we'd have to figure out for different situations. I'm providing this snippet but it has only been tested in a limited number of situations. If you are dealing with proxies, credentials, or other scenarios you'll have to massage this a bit.
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (s, e) =>
{
Uri uri = e.Argument as Uri;
using (WebClient webClient = new WebClient())
{
webClient.Proxy = null; //avoids dynamic proxy discovery delay
webClient.CachePolicy = new RequestCachePolicy(RequestCacheLevel.Default);
try
{
byte[] imageBytes = null;
imageBytes = webClient.DownloadData(uri);
if (imageBytes == null)
{
e.Result = null;
return;
}
MemoryStream imageStream = new MemoryStream(imageBytes);
BitmapImage image = new BitmapImage();
image.BeginInit();
image.StreamSource = imageStream;
image.CacheOption = BitmapCacheOption.OnLoad;
image.EndInit();
image.Freeze();
imageStream.Close();
e.Result = image;
}
catch (WebException ex)
{
//do something to report the exception
e.Result = ex;
}
}
};
worker.RunWorkerCompleted += (s, e) =>
{
BitmapImage bitmapImage = e.Result as BitmapImage;
if (bitmapImage != null)
{
myImage.Source = bitmapImage;
}
worker.Dispose();
};
worker.RunWorkerAsync(imageUri);
I tested this in a simple project and it works fine. I'm not 100% about whether it is hitting the cache, but from what I could tell from MSDN, other forum questions, and Reflectoring into PresentationCore it should be hitting the cache. WebClient wraps WebRequest, which wraps HTTPWebRequest, and so on, and the cache settings are passed down each layer.
The BitmapImage BeginInit/EndInit pair ensures that you can set the settings you need at the same time and then during EndInit it executes. If you need to set any other properties, you should use the empty constructor and write out the BeginInit/EndInit pair like above, setting what you need before calling EndInit.
I typically also set this option, which forces it to load the image into memory during EndInit:
image.CacheOption = BitmapCacheOption.OnLoad;
This will trade off possible higher memory usage for better runtime performance. If you do this, then the BitmapImage will be loaded synchronously within EndInit, unless the BitmapImage requires async downloading from a URL.
Further notes:
BitmapImage will async download if the UriSource is an absolute Uri and is an http or https scheme. You can tell whether it is downloading by checking the BitmapImage.IsDownloading property after EndInit. There are DownloadCompleted, DownloadFailed, and DownloadProgress events, but you have to be extra tricky to get them to fire on the background thread. Since BitmapImage only exposes an asynchronous approach, you would have to add a while loop with the WPF equivalent of DoEvents() to keep the thread alive until the download is complete. This thread shows code for DoEvents that works in this snippet:
worker.DoWork += (s, e) =>
{
Uri uri = e.Argument as Uri;
BitmapImage image = new BitmapImage();
image.BeginInit();
image.UriSource = uri;
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriCachePolicy = new RequestCachePolicy(RequestCacheLevel.Default);
image.EndInit();
while (image.IsDownloading)
{
DoEvents(); //Method from thread linked above
}
image.Freeze();
e.Result = image;
};
While the above approach works, it has a code smell because of DoEvents(), and it doesn't let you configure the WebClient proxy or other things that might help with better performance. The first example above is recommended over this one.
The BitmapImage needs async support for all of its events and internals. Calling Dispatcher.Run() on the background thread will...well run the dispatcher for the thread. (BitmapImage inherits from DispatcherObject so it needs a dispatcher. If the thread that created the BitmapImage doesn't already have a dispatcher a new one will be created on demand. cool.).
Important safety tip: The BitmapImage will NOT raise any events if it is pulling data from cache (rats).
This has been working very well for me....
var worker = new BackgroundWorker() { WorkerReportsProgress = true };
// DoWork runs on a brackground thread...no thouchy uiy.
worker.DoWork += (sender, args) =>
{
var uri = args.Argument as Uri;
var image = new BitmapImage();
image.BeginInit();
image.DownloadProgress += (s, e) => worker.ReportProgress(e.Progress);
image.DownloadFailed += (s, e) => Dispatcher.CurrentDispatcher.InvokeShutdown();
image.DecodeFailed += (s, e) => Dispatcher.CurrentDispatcher.InvokeShutdown();
image.DownloadCompleted += (s, e) =>
{
image.Freeze();
args.Result = image;
Dispatcher.CurrentDispatcher.InvokeShutdown();
};
image.UriSource = uri;
image.EndInit();
// !!! if IsDownloading == false the image is cached and NO events will fire !!!
if (image.IsDownloading == false)
{
image.Freeze();
args.Result = image;
}
else
{
// block until InvokeShutdown() is called.
Dispatcher.Run();
}
};
// ProgressChanged runs on the UI thread
worker.ProgressChanged += (s, args) => progressBar.Value = args.ProgressPercentage;
// RunWorkerCompleted runs on the UI thread
worker.RunWorkerCompleted += (s, args) =>
{
if (args.Error == null)
{
uiImage.Source = args.Result as BitmapImage;
}
};
var imageUri = new Uri(#"http://farm6.static.flickr.com/5204/5275574073_1c5b004117_b.jpg");
worker.RunWorkerAsync(imageUri);

Problem with WPF graph control

I've developed a graph control in GDI+ and used a timer in it.. now i'm converting it to
WPF. but when i went on and search for a timer there is no timers in WPF... how can i resolve this problem?any alternative to use?
regards,
rangana.
You can use System.Threading.Timer without any problems I suppose.
Here is an example of a timer which executes every 1 sec:
using System.Threading;
...
TimerCallback timerCallBack = OnTimerCallback;
Timer timer = new Timer(timerCallBack, null, 0, 1000);
...
private void OnTimerCallback(object state)
{
...
}
If you want to update any UI related elements from the timer, you will have to use Dispatcher.BeginInvoke because the timer runs in it's own thread and the UI is owned by the main thread which starts the timer. Here is an example:
private void OnTimerCallback(object state)
{
Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal,
(ThreadStart) (() => Background = Brushes.Black));
}
The timer you are looking for is DispatcherTimer http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatchertimer.aspx
But, if you plan to use a timer to drive animations, there are better ways to do that in WPF (just Google WPF animation).

Resources