I'm currently writing an application in C# and would like to allow external VB scripts to manipulate the WPF based GUI of the application in some way. Those scripts should be allowed to run very long and to pause the thread they are running in (it's a little slide-show like application where the VBScripts determine the content of the view at runtime). To accomplish this, I referenced the ScriptControl COM component and made my classes ComVisible. The selected script will be executed by a ScriptingHost like this:
public void Run(Action callback)
{
var thread = new Thread(() =>
{
_ScriptControl.Run("Execute", new object[] { }); // _ScriptControl is the COM component
callback();
});
thread.Start();
}
To display an image in my application, I use the following method in my view model (invoked from VBScript):
public void ShowPicture(string path)
{
BitmapImage bmImage = new BitmapImage();
bmImage.BeginInit();
bmImage.UriSource = new Uri(path, UriKind.Absolute);
bmImage.EndInit();
bmImage.Freeze();
_CurrentImage = bmImage;
RaisePropertyChanged("CurrentImage");
// System.Windows.Forms.Application.DoEvents();
}
The property CurrentImage
returns the newly created BitmapImage (_CurrentImage
) and is bound to an image control on my view.
When I run a script which will pause the scripting thread (to give the user some time to watch the picture) with Thread.Sleep()
, the image control will still fetch the CurrentImage
property after the event has been raised, but the picture will not be displayed. If I add a DoEvents
call or a MessageBox.Show
somewhere, the GUI will update properly.
I tried to display an image invoking the ShowPicture
method in a seperate thread followed by a Thread.Sleep()
and this works well (without the ScriptControl COM component).
Does the ScriptControl COM component use the UI thread in some way (I already set AllowUI
to false
) or is there some other mysterious COM stuff going on?
Example script:
Function Execute()
For Each picture In Source.GetPictures(False)
Canvas.ShowPicture(picture)
Host.Wait(5) ' Thread.Sleep(5000)
Next
End Function