using gridTest.doubleTapped += DoubleTapEvent actually very rarely detects the double tap.
Is there any work arunds or some thing to get that.
i provided a work around in my app by adding a dispatcher tier and that too keeping an interval of approx 300 milli seconds.
Heres dispatcher timer code
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = new TimeSpan(300);
timer.Tick += timer_Tick;
timer.Start();
public void timer_Tick(object sender, object args){ // handle the code here and dont forget to stop the timer}
I know this is a bad practice but it helps. and can be used as a work around if in hurry :)
Related
This question already has answers here:
How do I update the GUI from another thread?
(47 answers)
Closed 1 year ago.
Currently I am creating a background STA thread to keep the UI responsive but it slows down my function calls on the main thread.
Based on this thread How to update progress bar while working in the UI thread I tried the following but the UI only gets updated after all of the work has finished. I tried playing around with the Dispatcher priorities but none of them seem to work.
What I also tried is adding _frmPrg.Refresh() to my Progress callback but this does not seem to change anything.
Dim oProgress = New Progress(Of PrgObject)(Sub(runNumber)
_frmPrg.Invoke((Sub()
_frmPrg.Status = runNumber
End Sub))
End Sub)
System.Windows.Threading.Dispatcher.CurrentDispatcher.BeginInvoke(Sub()
DoLongRunningWork(oProgress, _cancellationToken)
End Sub, System.Windows.Threading.DispatcherPriority.Background)
I can't really help you with your problem, but I'll try to clarify what happens in your posted code.
DoLongRunningWork will be invoked through Dispatcher on the UI thread, when the UI thread is not busy. But once started, it will block the UI thread until it completes. So you can't show a progress this way. Your single chance is, to let DoLongRunningWork run on a background thread. That brings you nothing, if the long-running methods come from office objects, which must be accessed from the UI thread...
The Progress class (see the remarks section) invokes your event handler on the UI thread automatically, so you don't need _frmPrg.Invoke in your event handler.
Maybe you can start a STAthread for your progress form and show it from there. The instance of your Progress class must be created in this thread too, but not before your form is shown to ensure, that the thread becomes a WindowsFormsSynchronisationContext (or you set one explicitly after starting the thread). A plain SynchronisationContext won't work!
At least you get updates in your form this way, but the UI thread of the office app will still be blocked. And of course, any action you make with your progress form must be invoked on the UI thread, if accessing office objects.
After reading some other posts, I decided to suggest another solution. My previous answer still contains usable information, so I'll leave it there. I'm not familiar with VB.NET syntax, so the samples are in C#. I have tested the code in a VSTO plugin for PowerPoint, but it should run in any office application.
Forget the Progress class and background threads. Run everything on the UI thread!
Now use some async code. To stay on the UI thread, we need a "good" SynchronizationContext.
private static void EnsureWinFormsSyncContext()
{
// Ensure that we have a "good" SynchronisationContext
// See https://stackoverflow.com/a/32866156/10318835
if (SynchronizationContext.Current is not WindowsFormsSynchronizationContext)
SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());
}
This is the event handler of a button. Note the manually added async keyword. The SynchronizationContext.Current gets resetted again and again, so ensure the good one in the EventHandler:
private async void OnButtonClick(object sender, EventArgs e)
{
EnsureWinFormsSyncContext();
// Return from event handler, ensure that we are really async
// See https://stackoverflow.com/a/22645114/10318835
await Task.Yield();
await RunLongOnUIThread();
}
This will be the worker method, also running on the UI thread.
private async Task RunLongOnUIThread()
{
//Dummy code, replace it with your code
var pres = addIn.Application.Presentations.Add();
for (int i = 0; i < 100; i++)
{
Debug.Print("Creating slide {0} on thread {1}", i, Thread.CurrentThread.ManagedThreadId);
// If you have some workloads that can be run on a background
// thread, execute them with await Task.Run(...).
try
{
var layout = pres.Designs[1].SlideMaster.CustomLayouts[1];
var slide = pres.Slides.AddSlide(i + 1, layout);
var shape = slide.Shapes.AddLabel(Microsoft.Office.Core.MsoTextOrientation.msoTextOrientationHorizontal, 0, 15 * i, 100, 15);
shape.TextFrame.TextRange.Text = $"Text on slide {i + 1}";
}
catch (Exception ex)
{
Debug.Print("I don't know what am I doing here, I'm not familiar with PowerPoint... {0}", ex);
}
// Update UI
statusLabel.Text = $"Slide {i + 1} done";
progressBar1.Value = i + 1;
// This is the magic! It gives the main thread the opportunity to update the UI.
// It also processes input messages so you need to disable unwanted buttons etc.
await IdleYield();
}
}
The following method is for Windows Forms Applications where it does the job perfect. I've tried it also in PowerPoint. If you are facing problems, try the WPF flavour with await Dispatcher.Yield(DispatcherPriority.ApplicationIdle) instead of await IdleYield().
private static Task IdleYield()
{
var idleTcs = new TaskCompletionSource<bool>();
void handler(object s, EventArgs e)
{
Application.Idle -= handler;
idleTcs.SetResult(true);
}
Application.Idle += handler;
return idleTcs.Task;
}
Here are the (clickable) links to the answers that I used (I can't put them in the code-blocks...).
Incorrect async/await working, Excel events in Excel Application Level Add-in
When would I use Task.Yield()?
Task.Yield - real usages?
If in your real code something runs not as expected, check the thread you are running on and SynchronizationContext.Current.
We are developing a WPF application using TDD. As we're already working on this solution for almost two years, we've written a huge bunch of tests (almost 2000 Unittests right now).
There are some classes, that need to implement functionality multithreaded and asynchronously. For example a communication-component that can both send and receive messages and parse them. The dependencies are always mocked using RhinoMocks.
Our Test-Methods targeting these classes look very similar, as following:
[TestMethod]
public void Method_Description_ExpectedResult(){
// Arrange
var myStub = MockRepository.GenerateStub<IMyStub>();
var target = new MyAsynchronousClass(myStub);
// Act
var target.Send("Foo");
Thread.Sleep(200);
//Assert
myStub.AssertWasCalled(x => x.Bar("Foo"));
}
As you can see, this test runs at least for 200 ms due to the Thread.Sleep(). We optimized the test replacing the AssertWasCalled with a active polling method, s.th. like this:
public static bool True(Func<bool> condition, int times, int waitTime)
{
for (var i = 0; i < times; i++)
{
if (condition())
return true;
Thread.Sleep(waitTime);
}
return condition();
}
We can now use this WaitFor.True(...) Method by changing the AssertWasCalled to:
var fooTriggered = false;
myStub.Stub(x => x.Bar("Foo")).Do((Action)(() => fooTriggered = true)));
WaitFor.True(() => fooTriggered, 20, 20);
Assert.IsTrue(fooTriggered);
This construct will terminate earlier if the condition matches, but anyway - this takes too long for us. Running all of our 2000 Tests need about 5 Minutes (building and running them).
Is there any smart trick how we could optimize code like this?
You can use a monitor. I'm making this up so please excuse me if it isn't quite compiling, but it'll look something like:
[TestMethod]
public void Method_Description_ExpectedResult(){
// Arrange
var waitingRoom = new object();
var myStub = MockRepository.GenerateStub<IMyStub>();
myStub.Setup(x => x.Bar("Foo")).Callback(x =>
{
Monitor.Enter(waitingRoom);
Monitor.Pulse(waitingRoom);
Monitor.Exit(waitingRoom);
}
var target = new MyAsynchronousClass(myStub);
// Act
Monitor.Enter(waitingRoom);
target.Send("Foo");
Monitor.Wait(waitingRoom);
Monitor.Exit(waitingRoom);
//Assert
myStub.AssertWasCalled(x => x.Bar("Foo"));
}
Code written within the Monitor can't run until it's free. The test will cause the acting thread to wait until Monitor.Wait has been called. Then the callback can enter and pulse the Monitor. The test then "wakes up", and once the callback has exited the monitor, it gets control back and exits too, allowing you to Assert.
The only thing I haven't covered is that if Bar("Foo") doesn't get called it will hang, so you might want to have a timer pulse the thread too.
You can create a class which does the complex monitoring bits for you if you use it a lot. This is one I wrote to deal with asynchronous checks in UI automation; adapting it for what you're doing might help you.
My app is making heavy use of webservice calls. Lately, some of the calls got stuck. After playing around I figured out that it
happens mostly for release builds
happens in the Simulator AND on the device (iPad, iOS 4.3)
happens more often on iPad 1 than on iPad 2
it is not limited to web services an SOAP but also affects the System.Net.WebClient
does not affest [NSString stringWithContentsOfUrl:] if invoked manually, since not bound
The effect is that the CPU load of the device drops to zero. memory is stable (in my demo project 8.5MB). If I put Console.WriteLines() everywhere, I can see that the code is stuck inside one of the WebClient.Download*() methods.
The code below demonstrates that (if built RELEASE with MT 4.0.1, LLVM off or on does not matter) downloading a file from the web over and over again fails sometimes right away on the first try, sometimes after 10 times, sometimes after around 30 downloads.
It is totally random. If you think it works, kill the app and restart it and eventually it will hang.
When building the same using MT 3.2.6, the downloading goes on all day without issues. It is impossible to break it.
MONO installed is the latest available version.
Can somebody from the MT team comment on it?
using System;
using System.IO;
using System.Threading;
using System.Net;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
namespace iOSTest
{
public class Application
{
static void Main (string[] args)
{
UIApplication.Main (args);
}
}
// The name AppDelegate is referenced in the MainWindow.xib file.
public partial class AppDelegate : UIApplicationDelegate
{
private Thread oThread;
// This method is invoked when the application has loaded its UI and its ready to run
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
// Make a release build and run on iPad 1 with iOS 4.3.2.
// Fails after downloading between 1 time and 30 times on MT 4.0.1.
// It is possible that it seems to work. Then just kill the app and restart and suddenly the effect
// will become visible. If you watch it with Instruments, CPU suddenly drops to zero. The app then is
// stuck somewhere inside WebClient. After about 10 minutes, an exception will be thrown (timeout).
// Never fails on MT 3.2.6
Console.WriteLine(MonoTouch.Constants.Version);
// A label that counts how often we downloaded.
UILabel oLbl = new UILabel(new System.Drawing.RectangleF(40, 100, 150, 30));
window.AddSubview(oLbl);
// This thread downloads the same file over and over again.
// The thread is not required to demonstrate the issue. The same problem occurs
// if the download is running on the main thread.
this.oThread = new Thread(delegate()
{
using(var oPool = new NSAutoreleasePool())
{
int i = 0;
while(true)
{
// Setup webclient and download a file from my website (around 2.4 MB)
WebClient oClient = new WebClient();
// It would be nice to hange it to your own URL to save me from all the traffic.
oClient.DownloadFile(new Uri("http://www.wildsau.net/image.axd?picture=2011%2f4%2fDSC05178.JPG"), Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "test.jpg"));
// Increase counter and update label.
i++;
this.InvokeOnMainThread(delegate { oLbl.Text = i.ToString(); });
Console.WriteLine("Done " + i + " times.");
}
}
});
// Have a button that starts the action.
UIButton oBtn = UIButton.FromType(UIButtonType.RoundedRect);
oBtn.SetTitle("Download", UIControlState.Normal);
oBtn.Frame = new System.Drawing.RectangleF(40, 40, 150, 30);
oBtn.TouchUpInside += delegate(object sender, System.EventArgs e)
{
this.oThread.Start();
};
window.AddSubview(oBtn);
window.MakeKeyAndVisible ();
return true;
}
// This method is required in iPhoneOS 3.0
public override void OnActivated (UIApplication application)
{
}
}
}
From Gonzalo-
When the problem occurs, "kicking" the threadpool by adding another
work item will make the problem go away.
Something like this (not tested or compiled ;-) should do:
Timer timer = new Timer (AddMe);
...
WebClient wc = new WebClient ();
Uri uri = new Uri(url);
timer.Change (0, 500); // Trigger it now and every 500ms
byte[] bytes = wc.DownloadData(uri);
timer.Change (Timeout.Infinite, Timeout.Infinite);
....
static void AddMe (object state)
{
// Empty.
}
#
Works 100% of the time - for me at least - YMMV. And it did, once we put the code under stress (Lots of files to download) it stalled again. Just heard from MT that 4.0.6 will have the fix in it. Should see it later this week!
Promised to be fixed by Xamarin in the next major release. Still does not work in 4.0.4 though.
I'm hoping someone can help me with this. I have found the examples for recording audio using XNA in a Silverlight application. And it works, however, only the first time in. I have all the recording functionality on a seperate WP7 Page and with successive visits to the page it doesn't work. The best I can tell is the microphone.start is getting called but the micophone.status remains stopped. What is weird is the BufferReady keeps getting called and the code within that function is all running but without the microphone really starting nothing is really happening. When you exit the app and come back in again the first time visit to the page and everything works fine, but a revisit to the page and it doesn't.
void microphone_BufferReady(object sender, EventArgs e)
{
this.Dispatcher.BeginInvoke(() =>
{
microphone.GetData(buffer);
stream.Write(buffer, 0, buffer.Length);
TimeSpan tsTemp = timer.Elapsed;
TextBlockSeconds.Text = tsTemp.Hours.ToString().PadLeft(2, '0') + ":" + tsTemp.Minutes.ToString().PadLeft(2, '0') + ":" + tsTemp.Seconds.ToString().PadLeft(2, '0');
if(timer.Elapsed.Seconds >5)
DoStop();
});
}
private void ButtonRecord_Click(object sender, RoutedEventArgs e)
{
DisableRecordButton();
timer = new Stopwatch();
timer.Start();
stream = new MemoryStream();
TextBlockSeconds.Text = "00:00:00";
TextBlockStatus.Text = "Recording: ";
microphone.BufferDuration = TimeSpan.FromMilliseconds(500);
buffer = new byte[microphone.GetSampleSizeInBytes(microphone.BufferDuration)];
microphone.BufferReady += new EventHandler<EventArgs>(microphone_BufferReady);
microphone.Start();
}
private void DoStop()
{
if (timer.IsRunning)
timer.Stop();
if (microphone.State == MicrophoneState.Started)
{
microphone.Stop();
TextBlockStatus.Text = "Stopped: Ready to save";
}
else
{
TextBlockStatus.Text = "Ready: ";
}
TextBlockSeconds.Text = string.Empty;
EnableRecordButton();
}
Update...
I found the problem but no solution. I was calling the microphone.stop via code on a timer (so I could limit the recorded audio to 5 seconds). Exact same code to execute when a manual stop button would be clicked. When clicking the manual stop button everything worked fine, could re-visit the page and all would be fine. When the stop was called in code from the timer, next visit to the page would not work. So I implemented it with only a manual stop button but really would have been nice to do it automatically (and to know what the real issue was).
actually when you are navigating away from the page you can add
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
this.MicroPhone.BufferReady -= this.Microphone_BufferReady;
}
and when you are returning to page add
this.MicroPhone.BufferReady += this.Microphone_BufferReady;
You can add this statement either in a page loaded event or an OnNavigatedTo event
Added string name = System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() to make sure that it was on the same thread (and it was).
But finally worked this out, the problem is the microphone.stop doesn't stop the microphone from continuing to fire the buffer ready event (like I was expecting). And it would seem the way the page is cached this causes some weird problems with that event still firing. So I added the code
microphone.BufferReady -= new EventHandler<EventArgs>(microphone_BufferReady);
to my code for stopping, and it all works now.
I can't see from your code how you're stopping the timer/microphone if you navigate away from the page and don't manually stop it.
If that's not it, are you ensuring that all your microphone operations are being executed on the same thread? (Just a thought.)
I am trying to use the parallel task library to kick off a number of tasks like this:
var workTasks = _schedules.Where(x => x.Task.Enabled);
_tasks = new Task[workTasks.Count()];
_cancellationTokenSource = new CancellationTokenSource();
_cancellationTokenSource.Token.ThrowIfCancellationRequested();
int i = 0;
foreach (var schedule in _schedules.Where(x => x.Task.Enabled))
{
_log.InfoFormat("Reading task information for task {0}", schedule.Task.Name);
if(!schedule.Task.Enabled)
{
_log.InfoFormat("task {0} disabled.", schedule.Task.Name);
i++;
continue;
}
schedule.Task.ServiceStarted = true;
_tasks[i] = Task.Factory.StartNew(() =>
schedule.Task.Run()
, _cancellationTokenSource.Token);
i++;
_log.InfoFormat("task {0} has been added to the worker threads and has been started.", schedule.Task.Name);
}
I want these tasks to sleep and then wake up every 5 minutes and do their stuff, at the moment I am using Thread.Sleep in the Schedule object whose Run method is the Action that is passed into StartNew as an argument like this:
_tasks[i] = Task.Factory.StartNew(() =>
schedule.Task.Run()
, _cancellationTokenSource.Token);
I read somewhere that Thread.Sleep is a bad solution for this. Can anyone recommend a better approach?
By my understanding, Thread.Sleep is bad generally, because it force-shifts everything out of memory even when that's not necessary. It won't be a big deal in most cases, but it could be a performance issue.
I'm in the habit of using this snippet instead:
new System.Threading.EventWaitHandle(false, EventResetMode.ManualReset).WaitOne(1000);
Fits on one line, and isn't overly complicated -- it creates an event handle that will never be set, and then waits for the full timeout period before continuing.
Anyway, if you're just trying to have something repeat every 5 minutes, a better approach would probably be to use a Timer. You could even make a class to neatly wrap everything if your repeated work methods are already factored out:
using System.Threading;
using System.Threading.Tasks;
public class WorkRepeater
{
Timer m_Timer;
WorkRepeater(Action workToRepeat, TimeSpan interval)
{
m_Timer = new System.Timers.Timer((double)Interval.Milliseconds);
m_Timer.Elapsed +=
new System.Timers.ElapsedEventHandler((o, ea) => WorkToRepeat());
}
public void Start()
{
m_Timer.Start();
}
public void Stop()
{
m_Timer.Stop();
}
}
Bad solution are Tasks here. Task should be used for short living operations, like asynch IO. If you want to control life time of task you should use Thread and sleep as much as you like, because Thread is individual, but Tasks are rotated in thread pool which is shared.