I am doing a few processes that take time so I want to be able to show a mask, I use LoadMask. Problem is that the code that I want to run seems to run too quick and I presume is blocking the UI to show the mask. The process takes around 4 seconds so I know the mask isn't being enabled and disabled at the same time.
The way I got around this was to use a delayed task, but it kind of feels like a code smell.
Can I do this a different way?
Here is what I have
var myMask = new Ext.LoadMask(win, {});
myMask.show();
var task = new Ext.util.DelayedTask(function () {
....... // DO MY stuff and eventually do a myMask.hide()
task.delay(400);
It works great but I was wondering if this is the right way to go ?
If I remove the delayedtaks then the mask never seems to display, but the process does work.
Assuming your "process" is some kind of local sequential procedure, what you said above is pretty much correct. If your code is running a busy loop it won't relinquish control to the UI "thread" for the browser to redraw.
So you won't see the mask here;
mask();
busyLoop();
unmask();
But if you do:
mask();
setTimeout(function() {
busyLoop();
unmask();
}, 1);
It gives the browser time to draw before you get into your stuff.
Related
I'm looking for a method to wait for the GPU to finish its work in DirectX9. Something equivalent to the glFinish command in OpenGL...
I already know that it's not something I should do, but I have to! I'm writing a threaded Graphics Engine integrated in WPF and I need to make sort of an off-screen rendering in order to give a valid surface to a D3DImage. The frames are very long to compute (more than 100ms) and the rendering of the WPF Image sometimes occurs while the frame is not fully computed by my Engine even if I lock everything the right way. I'm almost sure it's just a Finish issue but I didn't find out how to do that.
So far, I tried to launch a DX9 query like this :
using namespace SlimDX.Direct3D9;
public class GraphicsDevice: Device
{
...
public void Finish()
{
var query = new Query(this, QueryType.Event);
EndScene();
while (!query.CheckStatus(true)) ;
}
}
But it does not seem to work...
So, first question without talking about WPF, do you know how to wait for the GPU to finish what has been sent to the driver?
Thanks!
This was the solution.
I was not aware that it actually work!
I used an EventQuery to 'mark' my last call to the GPU.
Then I put some kind of infinite loop flushing the GPU instructions and waiting for the EventQuery to be finally fired by the GPU, using the GetData/CheckStatus methods.
I am using the SharpDX.WPF project for the WPF abilities, it seems like an easy to understand low-overhead library, compared to the Toolkit that comes with SharpDX (which has the same issue!)
First: I fixed the SharpDX.WPF project for the latest SharpDX using the following: https://stackoverflow.com/a/19791534/442833
Then I made the following hacky adjustment to DXElement.cs, a solution that was also done here:
private Query queryForCompletion;
public void Render()
{
if (Renderer == null || IsInDesignMode)
return;
var test = Renderer as D3D11;
if (queryForCompletion == null)
{
queryForCompletion = new Query(test.Device,
new QueryDescription {Type = QueryType.Event, Flags = QueryFlags.None});
}
Renderer.Render(GetDrawEventArgs());
Surface.Lock();
test.Device.ImmediateContext.End(queryForCompletion);
// wait until drawing completes
Bool completed;
var counter = 0;
while (!(test.Device.ImmediateContext.GetData(queryForCompletion, out completed)
&& completed))
{
Console.WriteLine("Yielding..." + ++counter);
Thread.Yield();
}
//Surface.Invalidate();
Surface.AddDirtyRect(new Int32Rect(0, 0, Surface.PixelWidth, Surface.PixelHeight));
Surface.Unlock();
}
Then I render 8000 cubes in a cube pattern...
Yielding...
gets printed to the console quite often, but the flickering is still there.
I am assuming that WPF is nice enough to show the image using a different thread before the rendering is done, not sure though...
This same issue also happens when I use the Toolkit variant of WPF support with SharpDX.
Images to demonstate the issue:
Bad
Better
Almost
Intended
Note: It randomly switches between these old images, randomly. I am also using really old hardware which makes the flickering much more appearant (GeForce Quadro FX 1700)
A made a repo which contains the exact same source-code as I am using to get this issue:
https://github.com/ManIkWeet/FlickeringIssue/
Related to D3DImage locking, note that the D3DImage.TryLock API has rather unconventional semantics which most developers would not expect:
Beware!
You must call Unlock even in the case where TryLock indicates failure (i.e., returns false)
Although perhaps more of an alarming design choice than a bug per se, misunderstanding this behavior will trivially result in D3DImage deadlocks and hangs, and thus might be responsible for much of the frustration people experience in attempting to get D3DImage working properly.
The following code is a correct WPF D3D render with no flicker in my app:
void WPF_D3D_render(IntPtr pSurface)
{
if (TryLock(new Duration(default(TimeSpan))))
{
SetBackBuffer(D3DResourceType.IDirect3DSurface9, pSurface);
AddDirtyRect(new Int32Rect(0, 0, PixelWidth, PixelHeight));
}
Unlock(); // <--- !
}
Yes, this unintuitive code is actually correct; it is the case that that D3DImage.TryLock(0) leaks one internal D3D buffer lock every time it returns failure. You don't have to take my word for it, here's the CLR code from PresentationCore.dll v4.0.30319:
private bool LockImpl(Duration timeout)
{
bool flag = false;
if (_lockCount == uint.MaxValue)
throw new InvalidOperationException();
if (_lockCount == 0)
{
if (timeout == Duration.Forever)
flag = _canWriteEvent.WaitOne();
else
flag = _canWriteEvent.WaitOne(timeout.TimeSpan, false);
UnsubscribeFromCommittingBatch();
}
_lockCount++;
return flag;
}
Notice that the internal _lockCount field is incremented regardless of whether the function returns success or failure. You have to call Unlock() yourself, as shown in the first code example above, if you want to avoid certain deadlock. Failing to do so creates is nasty to debug, too, because the component won't (potentially) deadlock until the next render pass, by which time the relevant evidence is long gone.
The unusual behavior does not seem to be mentioned at MSDN, but to be fair, that documentation doesn't note that you have to call Unlock() if the call is successful, either.
The problem is not the Locking mechanism. Normally you use Present to draw to present the image. Present will wait until all drawing is ready. With D3DImage you are not using the Present() method. Instead of Presenting, you lock, adding a DirtyRect and unlock the D3DImage.
The rendering is done asynchrone so when you are unlocking, the draw actions might not be ready. This is causing the flicker effect. Sometimes you see items half drawn. A poor solution (i've tested with) is adding a small delay before unlocking. It helped a little, but it wasn't a neat solution. It was terrible!
Solution:
I continued with something else; I was expirimenting with MSAA (antialiasing) and the first problem I faced was; MSAA cannot be done on the dx11/dx9 shared texture, so i decided to render to a new texture (dx11) and create a copy to the dx9 shared texture. I slammed my head on the tabel, because now it was anti-aliased AND flicking-free!! Don't forget to call Flush() before adding a dirty rect.
So, creating a copy of the texture: DXDevice11.Device.ImmediateContext.ResolveSubresource(_dx11RenderTexture, 0, _dx11BackpageTexture, 0, ColorFormat); (_dx11BackpageTexture is shared texture) will wait until the rendering is ready and will create a copy.
This is how I got rid of the flickering....
I think you are not locking properly. As far as I understand the MSDN documentation you are supposed to lock during the entire rendering not just at the end of it:
While the D3DImage is locked, your application can also render to the Direct3D surface assigned to the back buffer.
The information you find on the net about D3DImage/SharpDX is somewhat confusing because the SharpDX guys don't really like the way D3DImage is implemented (can't blame them), so there are statements about this being a "bug" on Microsofts side when its actually just improper usage of the API.
Yes, locking during rendering has performance issues, but it is probably not possible to fix them without porting WPF to DirectX11 and implementing something like a SwapChainPanel which is available in UWP apps. (WPF itself still runs on DirectX9)
If the locking is a performance issue for you, one idea I had (but never tested) is that you could render to an offscreen surface and reduce the lock duration to copying that surface over to the D3DImage. No idea if that would help performance wise but its something to try.
I'm extending a GTK-application that does a group of operations that takes high CPU loads. I want to include the possibility to stop this operation by clicking on a button in the GUI.
The problem is that, as expected, the signal coming from the button is actually fired just after the operation is completed.
For now, the code kinda looks like this:
[...]
// code snippet to show the dialog and to enable user interactions with the buttons on the lower side of the window
while(TRUE) {
gint run = gtk_dialog_run (window_main);
if (run == GTK_RESPONSE_APPLY) {
gboolean success = start_long_operation();
}
else if (run == GTK_RESPONSE_HELP) {
open_about();
}
else if (run == GTK_RESPONSE_CANCEL) {
stop_long_operation();
}
else {
gtk_widget_destroy (window_main);
return;
}
}
I've declared a global variable busy_state that is checked by the long operation's function: if it is TRUE, simply the inner loop continues to cycle. Else, the loop exits and the function returns a result.
stop_long_operation() simply sets this global var to FALSE.
As written before, I can't press the "stop" button and "send" GTK_RESPONSE_CANCEL until the operation finishes, because it blocks the entire window.
I've tried the use of while (g_main_context_iteration(NULL, FALSE)) trick inside the stop_long_operation() function, as explained in the gtk's docs, but without results.
Do I really need to set up a multithread functionality? Can I avoid this?
Thanks for the help.
If you can break up your long operation into multiple smaller tasks you may be able to avoid using threads. The easiest way would be to just create a callback that you would pass to g_idle_add (or g_idle_add_full). Each time the callback runs it does a small amount of work, then returns TRUE. When the the task is completed, return FALSE and the callback not be run again. When you would like to interrupt the task, simply remove the callback by passing the value returned by g_idle_add to g_source_remove.
If you can't break up the operation then threads are pretty much your only choice. g_thread_new is the low-level way to do that, but it's generally easier to use a GThreadPool. A more advanced option would be to use g_simple_async_result_run_in_thread.
Here's another option if you don't want to use threads (although you should use threads and this is very insecure):
Use processes. Processes are much simpler, and can allow you some greater flexibility. Here's what you need to do:
Create another C/C++/Any language you want program that does the task
Spawn it using spawn() or popen()
(Optional) Pass arguments using the command line, or IPC
When the button is pressed, use either the kill() call on UNIX, or the Win32 kill function to kill the process. You can use SIGTERM on UNIX and register a handler so that you can have a controlled shutdown.
I want to understand why the number of timer keeps increasing whenever it is in use.
Should it start from a fresh number each time?
And why does it increase 2 or 4 each but not 1?
$(document).ready(function(){
endAndStartTimer();
});
var timer;
function endAndStartTimer() {
window.clearTimeout(timer);
//var millisecBeforeRedirect = 10000;
timer = window.setTimeout(function(){alert('Hello!');},1000);
alert(timer);
}
Do I need window.clearTimeout(timer); inside the function? What would it be wrong if I d
you can try it here.
Thanks.
Some simple facts
You don't have to call clearTimeout before setting one. At least not in the code you provided.
When I run your JSFiddle in FF4 it always reports 2
Timer IDs are generated by Javascript engine implemented in the browser so you don't have much control over it. Whatever it returns is value that you have to use to clear it. I haven't tested it but it may as well be that these ID generators are implement in a different way. Although the simplest (=fastest) way is by simply incrementing the ID of the last timer ID.
The method returns unique timer ID. The only purpose is to give you a handle to use it with clearTimeout. You can't control what id is generated.
The classic advice in multithreading programing is to do processor heavy work on a background thread and return the result to the UI thread for minor processing (update a label, etc). What if generating the WPF element itself is the operation which is expensive?
I'm working with a third party library which generates some intense elements, which can take around to 0.75s - 1.5s to render. Generating one isn't too bad, but when I need to create 5 of them to show at once it noticeably locks the UI (including progress spinners). Unfortunately, there isn't any other place to create them because WPF is thread affine.
I've already tried DispatcherPriority.Background but its not enough. What is the recommended way to deal with this problem?
If the objects being created derived from Freezable, then you can actually create them on a different thread than the UI thread - you just have to call Freeze on them while you're on the worker thread, and then you can transfer them over. However, that doesn't help you for items that don't derive from Freezable.
Have you tried creating them one at a time? The following example doesn't do any useful work but it does show how the basic structure for doing a lot of work in little bits:
int count = 100;
Action slow = null;
slow = delegate
{
Thread.Sleep(100);
count -= 1;
if (count > 0)
{
Dispatcher.BeginInvoke(slow, DispatcherPriority.Background);
}
};
Dispatcher.BeginInvoke(slow, DispatcherPriority.Background);
The 'work' here is to sleep for a tenth of a second. (So if you replace that with real work that takes about as long, you'll get the same behaviour.) This does that 100 times, so that's a total of 10 seconds of 'work'. The UI remains reasonably responsive for the whole time - things like dragging the window around become a bit less smooth, but it's perfectly usable. Change both those Background priorities to Normal, and the application locks up.
The key here is that we end up returning after doing each small bit of work having queued up the next bit - we end up calling Dispatcher.BeginInvoke 100 times in all instead of once. That gives the UI a chance to respond to input on a regular basis.