How Do I Add Background Thread To Silverlight Custom Control? - silverlight

I'm building a custom control for Windows Phone 7+ that can do augmented reality image processing. The control works wonderfully in practice (when I run the app), but because I have the image processing running on a separate thread, it breaks when I try to open the page in Blend or the Visual Studio designer.
Here's an example of the thread I'm trying to run (basically taken from http://msdn.microsoft.com/en-us/library/hh202982(v=vs.92).aspx) :
public override void OnApplyTemplate()
{
// assigning template stuff, initializing my camera
_myManualResetEvent = new ManualResetEvent(true);
_myCameraProcessingThread = new System.Threading.Thread(ProcessingMethod);
_myCameraProcessingThread.Start();
}
void ProcessingMethod()
{
int[] myBuffer = new int[640 * 480];
while(_someCondition)
{
_myManualResetEvent.WaitOne();
_myCamera.GetPreviewBufferArgb32(myBuffer);
// do my processing stuff
_myManualResetEvent.Set();
}
}
This breaks the ever-loving heck out of Blend. Would love to know why.

It looks like you are doing a lot of run-time stuff in the OnApplyTemplate method.
This will get called when Blend or Visual Studio instantiates the design view of your control.
You should either check to see if you are in design mode using the DesignMode:
if (!DesignMode)
{
_myManualResetEvent = new ManualResetEvent(true);
_myCameraProcessingThread = new System.Threading.Thread(ProcessingMethod);
_myCameraProcessingThread.Start();
}
or move this code into a method/event handler that only gets called when the application actually runs.

Related

How to use WPF UserControls or Windows from inside Visual FoxPro 9

I have a very, very large and complex Visual FoxPro 9 application. I'd like to rewrite portions of this application in WPF with the ultimate goal of completing cutting over a couple of years from now. I've spent a considerable amount of time searching google and stackoverflow for an end to end "hello world" type sample of how to implement this with COM interop. Found bits and pieces but nothing complete that shows both the FoxPro side and the WPF side.
My gut tells me I'm likely to run into issues with XAML resources, third party controls, or other normal functionalities of a WPF app if I try to run it via COM Interop.
So, two questions. Can anyone point me to an small end to end sample that either launches WPF windows from FoxPro or lets me drop WPF user controls on a FoxPro form? Or am I right with my concerns of potential interop issues and should avoid this altogether? If so, is there a recommended way for these two executables to communicate with each other?
I have absolutely no idea whether you can run wpf inside visual FoxPro. I would guess you'd have to write it as an activex.
I recently did some work extending a MS Access app.
My wpf app is completely separate and runs alongside the ms access app.
I communicated between the two using MS Message Queue - which is a com component.
Maybe this sort of approach could work for you.
When I wanted to show a screen in wpf from access I added a piece of xml to the local message queue.
The wpf app listens for these messages, casts them to objects which tells it which screen to show and gives it any parameters.
MS Access subscribes to the received message event on the message queue and that way it can tell when the wpf window closes and the user is done.
This was intended to use the strangler pattern to gradually replace functionality in the old access app.
Here's some code for the queuelistener that drives everything. The various pop classes are deserialised from the message and I build that as a string in access.
internal class QueueListener
{
public const string qFromMadge = #".\private$\XXXXQ";
public static string qToMadge = #".\private$\XXXXReturnQ";
private MessageQueue mq;
internal QueueListener()
{
try
{
SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
SubscribeHandler();
var mqSend = setUpQueue(qToMadge);
mqSend.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.InnerException.Message);
}
}
private MessageQueue setUpQueue(string qName)
{
MessageQueue q;
if (MessageQueue.Exists(qName))
{
q = new MessageQueue(qName);
}
else
{
q = MessageQueue.Create(qName);
}
q.ResetPermissions();
q.SetPermissions("Everyone", MessageQueueAccessRights.FullControl, AccessControlEntryType.Set);
q.Purge();
return q;
}
private void ReceiveMsgCompleted(Object source, ReceiveCompletedEventArgs asyncResult)
{
MessageQueue mq = (MessageQueue)source;
Message m = mq.EndReceive(asyncResult.AsyncResult);
m.Formatter = new XmlMessageFormatter(new[] { "XXXX.Popaaaa, XXXX"
, "XXXX.Popbbbb, XXXXX"
, "XXXX.Popcccc, XXXX"
, "XXXX.Popdddd, XXXX"
});
((BasePopView) m.Body).Pop();
mq.BeginReceive();
}
public void UnsubscribeHandler()
{
if (mq == null)
{
return;
}
mq.Close();
mq.ReceiveCompleted -= new ReceiveCompletedEventHandler(ReceiveMsgCompleted);
mq = null;
}
public void SubscribeHandler()
{
if(mq != null)
{
return;
}
mq = setUpQueue(qFromMadge);
mq.ReceiveCompleted += ReceiveMsgCompleted;
mq.BeginReceive();
}

How to stop User Control execution process until the User responds to the user control

Hi we have a WPF Application which we have developed using MVVM pattern. We have such kind of architecture where we have some DLLs which contain some POP UPs (WPF Windows) which are no where realeted to our Main Application.
Using some internal layer we are doing some analysis and dynamically picking the required dlls based on some conditions and we are showing those pop ups on main application by joining the thread of that dll with the WPF main application thread.
But now we want to remove those pop ups and instead of pop ups we want to show usercontrols in main window by replacing all these windows with usercontrol.
So now also we faced some issue with thread in dlls , and from dlls again we are sending the usercontrol object to main application and able to load in main application.
But earlier while showing pop ups we used the window.ShowDialog which will stop the further processing in that dll untill user responds.
But as now we changed those windows to usercontrols and we dont have any such mechanism in usercontrol which will stop further processing untill user responds to it, so before user responds the execution in dll is goinng to next level which we dont want.
Can any one help how to get the Window.ShowDialog() equivalent functionality while displaying or loading a User Control as well?
We tried setting up some flags in an infinite loop in usercontrol untill user responds , but we are getting again wpf thread issues even there.
Hi this is the code snippet and details as well:
We have one DLL called some XYZTest.dll which is of type user library where we have some wpf window which will be invoked from the same DLL from some other class Package.cs as follows earlier:
Initial Pop Up Approach where we are showing WPF window from dynamically invoked dll as pop up on the main application :
If(somecount>0)
{
MessagePanel messagePanel=new MessagePanel(request.ClientInfo.IPAddress);
messagePanel.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
messagePanel.ShowDialog();
}
Return obj;
In this above code untill user responds to the above window the execution process does not go further…
And this XYZTest.dll is dynamically invoked by a business layer and there using the following code we are attaching this thread to main application or thread which is our ui…
Dynamic Invocation of that DLL and joining thread to main window:::
Thread thread = new Thread((ThreadStart)delegate { retrunObject = invoke(requestObject); });
thread.SetApartmentState(ApartmentState.STA); //Set the thread to STA
thread.Start();
thread.Join();
return retrunObject;
But now we don’t want to display pop ups and so I wanted to change all the windows to user controls and wanted to display the respected user control in the main application dynamically.
So now we changed code something like this...
1st approach::
PangaeaServerApplication.App.Current.Dispatcher.Invoke((Action)(() =>
{
MessagePanelUserControl userControl = new MessagePanelUserControl();
MainApplication.ViewModel.MainWindowViewModel.ADDClientUUTPopUP( userControl);
while (true)
{
if (isRunning == false)
{
break;
}
else
{
userControl.trigger.WaitOne(2000);
}
}
}));
2nd Approach::
Thread newWindowThread = new Thread(new ThreadStart(() =>
{
// Create our context, and install it:
SynchronizationContext.SetSynchronizationContext(
new DispatcherSynchronizationContext(
Dispatcher.CurrentDispatcher));
MessagePanelUserControl userControl = new MessagePanelUserControl ();
MainApplication.ViewModel.MainWindowViewModel.ADDClientUUTPopUP(userControl);
while (true)
{
if (isRunning == false)
{
break;
}
else
{
userControl.trigger.WaitOne(2000);
}
}
System.Windows.Threading.Dispatcher.Run();
}));
newWindowThread.SetApartmentState(ApartmentState.STA);
// Make the thread a background thread
newWindowThread.IsBackground = true;
// Start the thread
newWindowThread.Start();
Here my intention is to achieve a behaviour similar to messagePanel.ShowDialog(); where the execution will not proceed further ...but while using autoresentevent I am getting complete ui hanged and if I am not using any timers and all then not able to stop execution untill user responds...

Launching a CustomAction UI written with WPF from a WIX installer: Fail on STAThread issue

My WIX installer launches an immediate custom action.
The custom action starts a WPF dialog prompting the user for a BD connection parameters (I basically wrote the 'new connection' DB prompter dialog in WPF, to get me a connection string that the custom action can inject in the installed application's configuration file).
The WIX code is fairly simple to figure out, and I know I execute the custom action just fine - I put there a MessageBox and a MmsiBreak on the call to my custom action method. I get there without a problem.
When the custom action instantiates my WPF dialog window, I get an InvaliOperationException: "The calling thread must be STA, because many UI components require this".
The same code runs fine when I put it in a standard WPF application, because VisualStudio generates boiler plate code with Main() that has a STAThreadAttribute on it.
I can't tack that attribute on the msiexec caller, and if I try to set the thread apartment state in my custom action, it fails:
Thread.CurrentThread.SetApartmentState(ApartmentState.STA);
Is not supposed to work for framework past 2.0.
Is there any way to do what I'm trying to do here? I'd appreciate some pointers.
EDIT
I even tried to run the dialog in its own thread, e.g. the code is like this:
// Static class members
static ManualResetEvent _done = new ManualResetEvent(false);
static ActionResult _caResult;
static Session _session;
static Thread _worker;
[CustomAction]
static public ActionResult PromptForDB(Session session)
{
_session = session;
_worker = new Thread(WorkerThread);
_worker.Start();
_done.WaitOne();
return _caResult;
}
[STAThread]
static void WorkerThread()
{
try
{
Prompter wnd = new Prompter();
if (!(bool)wnd.ShowDialog())
{
_caResult = ActionResult.SkipRemainingActions;
}
else
{
// Harvest our properties (omitted from this post)
_caResult = ActionResult.Success;
}
catch (Exception ex)
{
_caResult = ActionResult.Failure;
_session.Log("Error: " + ex.Message);
}
finally
{
_done.Set();
}
}
That does not work either.
Before starting your new thread, set its ApartmentState as follows:
_worker.SetApartmentState(ApartmentState.STA);
See this:
The calling thread must be STA, because many UI components require this in WPF

Debugging silverlight in a WPF app

I am developing a WPF app that contains a webbrowser control that loads a silverlight application. I would like to be able to launch the app from visual studio (F5) and have the debugger attach to the silverlight code. However, I've not had any luck with this.
The best I can currently do is to launch the app without attaching, then once it is up and running, attach to the process manually with silverlight as the specified type of code to debug, and this works. (When I cause the web browser control to load the silverlight app, it will hit breakpoints in my silverlight code). I've written some macros to automate this launching/attaching somewhat, but it still isn't the best.
I've tried specifying the WPF app as the external program to run when launching/debugging the silverlight app, but Visual Studio attaches to the process wanting to debug the managed .NET code.
Any ideas? Ideally, I would really like to attach to the process and debug both the managed .NET and the silverlight code, but I don't think this is possible. I'd really like to automatically be attached to the silverlight code at launch so that I can easily debug all issues with the silverlight app, including those that occur on load.
Thanks for your ideas Brandorf and fatty. Brandorf's almost gets me to where I wanted to go, but does require that my SL app be capable of running on its own. I really want to have only the one app, which is both wpf and silverlight, with the SL side being debugged.
A long time after I asked this question (I forgot I had asked it here), I actually pieced together a solution that I'm really happy with. I use visual studio automation within the WPF/.NET side of my app, to find all running instances of visual studio, figure out which one produced my exe (since it typically sits in a folder below the vcproj/sln folder), and then use visual studio automation to have that VS attach to the app, debugging silverlight code. After this is done, I then load my silverlight content.
It works really well. You end up with an app that goes and finds a debugger to attach to itself every time it runs (so you probably want this code only in a debug build, or somehow able to be turned off). So you just launch the app with ctrl-F5 (launch without debugging) from visual studio whenever you want to debug the silverlight side.
Here's my code:
#if DEBUG
using System;
using System.Collections.Generic;
using System.Collections;
using System.Runtime.InteropServices;
using System.IO;
namespace Launcher
{
//The core methods in this class to find all running instances of VS are
//taken/inspired from
//http://www.codeproject.com/KB/cs/automatingvisualstudio.aspx
class DebuggingAutomation
{
[DllImport("ole32.dll")]
private static extern int GetRunningObjectTable(int reserved,
out UCOMIRunningObjectTable prot);
[DllImport("ole32.dll")]
private static extern int CreateBindCtx(int reserved,
out UCOMIBindCtx ppbc);
///<summary>
///Get a snapshot of the running object table (ROT).
///</summary>
///<returns>
///A hashtable mapping the name of the object
///in the ROT to the corresponding object
///</returns>
private static Hashtable GetRunningObjectTable()
{
Hashtable result = new Hashtable();
int numFetched;
UCOMIRunningObjectTable runningObjectTable;
UCOMIEnumMoniker monikerEnumerator;
UCOMIMoniker[] monikers = new UCOMIMoniker[1];
GetRunningObjectTable(0, out runningObjectTable);
runningObjectTable.EnumRunning(out monikerEnumerator);
monikerEnumerator.Reset();
while (monikerEnumerator.Next(1, monikers, out numFetched) == 0)
{
UCOMIBindCtx ctx;
CreateBindCtx(0, out ctx);
string runningObjectName;
monikers[0].GetDisplayName(ctx, null, out runningObjectName);
object runningObjectVal;
runningObjectTable.GetObject(monikers[0], out runningObjectVal);
result[runningObjectName] = runningObjectVal;
}
return result;
}
/// <summary>
/// Get a table of the currently running instances of the Visual Studio .NET IDE.
/// </summary>
/// <param name="openSolutionsOnly">
/// Only return instances that have opened a solution
/// </param>
/// <returns>
/// A list of the ides (as DTE objects) present in
/// in the running object table to the corresponding DTE object
/// </returns>
private static List<EnvDTE.DTE> GetIDEInstances(bool openSolutionsOnly)
{
var runningIDEInstances = new List<EnvDTE.DTE>();
Hashtable runningObjects = GetRunningObjectTable();
IDictionaryEnumerator rotEnumerator = runningObjects.GetEnumerator();
while (rotEnumerator.MoveNext())
{
string candidateName = (string)rotEnumerator.Key;
if (!candidateName.StartsWith("!VisualStudio.DTE"))
continue;
EnvDTE.DTE ide = rotEnumerator.Value as EnvDTE.DTE;
if (ide == null)
continue;
if (openSolutionsOnly)
{
try
{
string solutionFile = ide.Solution.FullName;
if (!String.IsNullOrEmpty(solutionFile))
{
runningIDEInstances.Add(ide);
}
}
catch { }
}
else
{
runningIDEInstances.Add(ide);
}
}
return runningIDEInstances;
}
internal static void AttachDebuggerIfPossible()
{
if (System.Diagnostics.Debugger.IsAttached)
{
//Probably debugging host (Desktop .NET side), so don't try to attach to silverlight side
return;
}
var ides = GetIDEInstances(true);
var fullPathToAssembly = System.Reflection.Assembly.GetExecutingAssembly().Location;
var potentials = new List<EnvDTE.DTE>();
foreach (var ide in ides)
{
var solutionPath = ide.Solution.FullName;
var topLevelSolutionDir = Path.GetDirectoryName(solutionPath);
var assemblyName = fullPathToAssembly;
if (assemblyName.StartsWith(topLevelSolutionDir, StringComparison.OrdinalIgnoreCase))
{
potentials.Add(ide);
}
}
EnvDTE.DTE chosenIde = null;
//If you have multiple ides open that can match your exe, you can come up with a scheme to pick a particular one
//(eg, put a file like solution.sln.pickme next to the solution whose ide you want to debug). If this is not a
//concern, just pick the first match.
if (potentials.Count > 0)
{
chosenIde = potentials[0];
}
var dbg = chosenIde != null ? (EnvDTE80.Debugger2)chosenIde.Debugger : null;
if (dbg != null)
{
var trans = dbg.Transports.Item("Default");
var proc = (EnvDTE80.Process2)dbg.GetProcesses(trans, System.Environment.MachineName).Item(Path.GetFileName(fullPathToAssembly));
var engines = new EnvDTE80.Engine[1];
engines[0] = trans.Engines.Item("Silverlight");
proc.Attach2(engines);
}
}
}
}
#endif
It's a bit of a shot in the dark, but assuming your silverlight app is capable of running on its own, you can, under your solution settings, set visual studio to start both apps together, and you should be attached to both of them.
If you can't add the Silverlight project to your solution (which will start debugging automatically), you might be able to make use of this tip. It will load both projects at the same time
http://saraford.net/2008/07/28/did-you-know-you-can-start-debugging-multiple-projects-268/

What is the simplest way to display (and change) an image resource on a WPF dialog (using C++/CLI)?

I have a C++/CLI GUI application and I want to display an image as a visual aid for the user to see what step in a procedure they're at. This image will need to be changed each time the user selects the new step.
Currently I'm using a picture box and have an image loaded from the disk at run time. So there are a few things I need to know here:
Is a picture box the best thing to use for this purpose or is there another control that would better suit?
How do embed the images in the executable and load them from there instead of a file that exists on disk.
How do I load a new image (I'm guessing that this will be fairly obvois if I can crack point 2)?
I've seen a few answers which relate to C# but I've not seen anything which looks like it translates to doing things in a C++/CLI app. Any suggestions would be very welcome.
Well it may not be the best solution, but the following works.
Create a new Windows Forms Application
Add these libraries to your linker settings (Project Proerties -> Link -> Input -> Additional Dependencies):
User32.lib Gdi32.lib
Add these headers:
#include <windows.h>
#include "resource.h"
Add these namespaces:
using namespace System::Reflection;
using namespace System::Runtime::InteropServices;
Add a pair of bitmaps to your resources and call them IDB_BITMAP1 and IDB_BITMAP2.
Add a picture box called m_pictureBox1.
Add a button and double-click the button to add an on-click handler:
System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
// Remove any previously stored images
if(m_pictureBox1->Image != nullptr)
{
delete m_pictureBox1->Image;
}
// Pick a new bitmap
static int resource = IDB_BITMAP1;
if( resource == IDB_BITMAP2)
{
resource = IDB_BITMAP1;
}
else
{
resource = IDB_BITMAP2;
}
// Get the primary module
Module^ mod = Assembly::GetExecutingAssembly()->GetModules()[0];
// Get the instance handle
IntPtr hinst = Marshal::GetHINSTANCE(mod);
// Get the bitmap as unmanaged
HANDLE hbi = LoadImage((HINSTANCE) hinst.ToPointer(),MAKEINTRESOURCE(resource),IMAGE_BITMAP,0,0,LR_DEFAULTCOLOR);
// import the unmanaged bitmap into the managed side
Bitmap^ bi = Bitmap::FromHbitmap(IntPtr(hbi));
// insert the bitmap into the picture box
m_pictureBox1->Image = bi;
// Free up the unmanaged bitmap
DeleteObject(hbi);
// Free up the instance and module
delete hinst;
delete mod;
}
..et voila the bitmaps are stored neatly in you app and each time you click the button the images will swap.

Resources