WordPress database error: [INSERT, UPDATE command denied to user '51213-2'@'10.10.20.25' for table 'wp_options']INSERT INTO `wp_options` (`option_name`, `option_value`, `autoload`) VALUES ('_transient_doing_cron', '1715238073.7555229663848876953125', 'yes') ON DUPLICATE KEY UPDATE `option_name` = VALUES(`option_name`), `option_value` = VALUES(`option_value`), `autoload` = VALUES(`autoload`)
We wil do this using DirectX and Unity.
As you can see in this video, the “context” of the leaved Windows is kept : the scroll position does not change.
Since a long time now, you can open a new Windows from a Windows Store app (UWP or Universal). For instance, the Mail app does this to let you edit an email in another dedicated window.
To perform this, you have to ask the SDK to create a new View (CoreApplicationView) which maps to a Window (CoreWindow) and an associated Dispatcher. This last point is interesting because you have to be very careful, when you share your ViewModels between windows, to be on the good Dispatcher when raising INotifyPropertyChanged event or doing some UI-related work.
Here is the code to create a Window :
// récupération de l'id courant pour usage ultérieur var appViewId = ApplicationView.GetForCurrentView().Id; //Create a new view \o/ CoreApplicationView newCoreAppView = CoreApplication.CreateNewView(); await newCoreAppView.Dispatcher.RunAsync( Windows.UI.Core.CoreDispatcherPriority.Low, () => { //Get the created Windows Window window = Window.Current; ApplicationView newAppView = ApplicationView.GetForCurrentView(); // create a new frame and navigate to the page var secondFrame = new Frame(); window.Content = secondFrame; secondFrame.Navigate(typeof(MainPage)); // activate the new Window window.Activate(); // make the new window standalone ApplicationViewSwitcher.TryShowAsStandaloneAsync(newAppView.Id, ViewSizePreference.UseMore, appViewId, ViewSizePreference.Default); });
By providing no argument to the CreateNewView method, we ask the XAML framework to create and manage a XAML UI.
We could also provide an argument of type IFrameworkViewSource to be able to have our own Window managed by our code. This is what DirectX does and it will let us create holograms !
By using the “HolographicDirectXApp” Visual Studio sample, I have all I need to create and display a 3D rotating cube by. The generated code creates an instance of IFrameworkView using DirectX. The sample use SharpDX, some C# classes and shaders that I can simply copy/Paste directly in a new XAML UWP project.
I then only have to use the previous snippet and ask it to use the DirectX AppView.
I have to carefully :
Of course, as all 3D holographic view, my start screen and the 2D View will disappear to let only the 3D objects in my space.
An Unity app being an UWP app the code to write will be very similar. We will only have to customize the generated Unity code to stay in a 2D World instead of going directly to the 3D exclusive View.
To be in the right configuration, I generate a XAML project instead of a Direct3D player in Unity. I then have this :
To have a “standard” Xaml project, I then perform these modifications :
The next steps are easy : I create a new Window, add a frame in it and navigate to the MainPage. I use exactly the same snippet as before and I only have to register an event handler to the activation of the created Window to be able to initialize Unity then. I also store the main view’s Id for further use.
private async Task CreateNewHoloWindowAsync() { var appViewId = MainAppViewId = ApplicationView.GetForCurrentView().Id; var _newCoreAppView = CoreApplication.CreateNewView(); await _newCoreAppView.Dispatcher .RunAsync(CoreDispatcherPriority.Low, async () => { var frame = new Frame(); Window.Current.Content = frame; frame.Navigate(typeof(MainPage)); var res = await ApplicationViewSwitcher.TryShowAsStandaloneAsync( ApplicationView.GetForCurrentView().Id, ViewSizePreference.Default, appViewId, ViewSizePreference.Default); _newCoreAppView.CoreWindow.Activated += WindowActivated; _newCoreAppView.CoreWindow.Activate(); }); } private void WindowActivated(object sender, WindowActivatedEventArgs e) { if (e.WindowActivationState == CoreWindowActivationState.CodeActivated || e.WindowActivationState == CoreWindowActivationState.PointerActivated) { AppCallbacks.Instance.SetInitialViewActive(); // Only need to mark initial activation once so unregister ourself CoreWindow coreWindowSender = sender as CoreWindow; coreWindowSender.Activated -= WindowActivated; } }
To go back to the 2D XAML view, you have to use the ApplicationViewSwitcher class and ask it to go switch back to the main Window.
I provide my Unity’s code an Action (GoBackToEarth.CloseThisHolographicView) it can call when needed.
// let's capture the dispatcher of the current view var dispatcher = Dispatcher; GoBackToEarth.CloseThisHolographicView = () => { // be sure to be on the Window's Dispatcher dispatcher.RunIdleAsync(async _ => { // go back to the main Window await ApplicationViewSwitcher.SwitchAsync(StartupPage.MainAppViewId); // we close the 3D holographic Window Window.Current.Close(); }); };
Happy coding !
]]>The Dispatcher class is maybe one of the most used in WPF when you start doing thing asyncronously. It is the only way to update UI controls from an another thread.
Even if it was easy to use, the WPF teams added 13 methods which will ease up this. Especially with the new await keyword. In this post we will discover these new methods.
There is some overload which takes as a param a Func delegate. Where in prior versions, the available methods on the Dispatcher were not able to return something (except void) it is now possible.
The new methods of this kind are :
Prior to WPF 4.5, to return something, this code should have been written:
[csharp]//The function which returns something (here of type object)
Func<object> myReturningObjectFunction = () =>
{//For example only !
return new object();
};
object returnedOject = null;
//A mock action to be abble to return the object
Action mockAction = () => { returnedOject = myReturningObjectFunction(); };
//Actually invoke the method
Dispatcher.CurrentDispatcher.Invoke(mockAction, null);
//Here I can use the returned object
[/csharp]
Now, you can write a more maintanable code by using this one:
[csharp]public void CallingMethod()
{
object returnedOject = Dispatcher.CurrentDispatcher
.Invoke(MyReturningObjectFunction, null);
}
//This method can now live alone !
private object MyReturningObjectFunction()
{
//For example only !
return new object();
}
[/csharp]
You surely are aware of the new-born ‘await’ keyword.
The WPF team is too and the Dispatcher is now await-ready !
Here is the new methods which are await-ready:
These method returns objects of the DispatcherOperation/DispatcherOperation
You can then use the await keyword on it or on its ‘Task’ property.
Here is an example:
[csharp]public async void CallingMethod()
{
await Dispatcher.CurrentDispatcher.InvokeAsync(MyReturningObjectFunction);
}
[/csharp]
Also, you can do some synchronisation and wait for a Dispatcher operation to be finished by using the DispatcherOperationWait method on the task. This is an extension method of the TaskExtensions class (available on System.Windows.Threading).
[csharp]DispatcherOperation<object> dispatcherOperation =
Dispatcher.CurrentDispatcher.InvokeAsync(MyReturningObjectFunction);
dispatcherOperation.Task.Wait();
[/csharp]
There is a disclaimer/warning on this last one “Calling Task.Wait will result in a deadlock if the operation is queued on a calling thread. For more information about using a Task to perform asynchronous operations, see Task Parallelism (Task Parallel Library).”
Finally, you may have noticed the new parameter of type CancellationToken.
This is part of the .NET 4 Cancellation Framework.
Under the hood, the Dispatcher operation you start creates a Task object which will be regulated by this cancellation token.
If the Task has not started, ie. your dispatcher operation has not, then it won’t start. If it has started it won’t be stopped and then continue its execution.
In fact, it’s up to the task’s action to check the cancellation token to stop itself. However, I didn’t find a way to pass the Cancellation token to the given Action instead of using the same trick I presented on the first paragraph about the returned object.
I didn’t find a scenario in which using the cancellation token is necessary but I think it’s coming from the things necessary to make the async keyword work.
This kind of scenario is a bit hard to reproduce in a demo but I managed to get a working example:
[csharp]//Create a token source
var cts = new CancellationTokenSource();
//Launch the cancel of the token
Task.Factory.StartNew(() => cts.Cancel());
//Launch an operation with priority normal
// this will delay the execution of the following Invoke call.
Dispatcher.BeginInvoke(new Action(() =>
{
int i = 0; while (i < 300)
//Update the UI to be sure to block the following
// action. Rendering will occur and takes precedence
{ i++; _counterTextBlock.Text = i.ToString(); }
}), null);
try
{
//Launch a task with the cancellation token
Dispatcher.Invoke(() => { while (true);},
DispatcherPriority.Background, cts.Token);
}
catch (OperationCanceledException ex)
{
//We are here because the token was cancelled
Console.WriteLine("The operation didn’t even start !");
}
[/csharp]
As a bonus you also have two new methods which add nothing special except an easier use :
You can also find the Dispatcher documenation on MSDN.
Regards,
]]>WPF is really awesome to build reactive applications and data binding is here to push useful information inside of the User Interface. All is done magically and it’s wonderfully simple to create an application without knowledge of the internals of the WPF’s rendering.
Now, I wan’t to talk about something which can useful in every WPF application : how to wait for the rendering UI to be done. This can also be rephrased to : “how to force the rendering after I performed an action ?“.
You can find a lot of reasons to need this:
Here is a non-exhaustive list of things that can only be done on the UI-Thread and which are time-consuming (if you have some others, please give me them in the comments):
What is wonderful is that the solution takes only one little line of code. One line of code.
To keep it simple, the rendering of the UI is perform on the UI thread via the Dispatcher. It can be considered as a tasks processer, each of these task being assigned a priority. The rendering of the UI is one of these tasks and all you have to do is tell the Dispatcher: “perform an action now with a priority less than the rendering”. The current work will then wait for the rendering to be done.
Here is the snippet this sentence transposing in .Net:
[csharp]Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle, null);[/csharp]
I promised: only one line of code.
The code starts an empty action via the Dispatcher’s Invoke method. The priority given to the Dispatcher is ContextIdle which is lesser that Render so the Dispatcher will wait for the rendering to be done before to execute the empty action(I agree that waiting to do nothing is quite strange but.. ).
Because the call to Invoke is blocking, your code won’t go on until the rendering is effectively done.
That is exactly what is required.
Of course there is! And a big one named ‘performance’. By doing the calls to Dispatcher.Invoke, you are forcing a switch between thread execution and it costs a lot of processing which can be disastrous in term of performance. My disclaimer is so: do this only when necessary, really necessary.
By the way, you can quite easily limit the occurrence of the context switches by doing the call every X(where X can be 5…) added items instead of after each item add.
I discovered that when I use this technique inside of the Loaded event handler of a Windows, it’s content was staying white until the long-running job stops. To make it work, I started the job in the ContentChanged method to be sure the content is rendered once first. Notice that it’s necessary only when you need to execute a long-running job on the UI-thread.
[csharp] protected override void
OnContentChanged(object oldContent, object newContent)
{
base.OnContentChanged(oldContent, newContent);
Dispatcher.BeginInvoke(new Action(MyLongProcessing), null);
}[/csharp]
That’s all for today, feel free to add comments
]]>