I have a WPF Project "ActiveX" that is registered for COM Visibility.It has a class "ActiveX".I am trying to create an object of another WPF Project's "MainApplication" MainWindow
The ActiveX class has two methods 1)Initialize 2)Close
1)Initialize API -- initializes and launches the mainwindow of the "MainApplication"
2)Close API -- Tries to close the instance created by the Initialize API
The problem is:
When the Close API is called the application is not closed completely. That is the Window is getting closed,Yet the thread is running in the background.
Could anyone suggest the proper exit of the Application called as ActiveX
using MainApplication;
//This interface is registered for COM
public interface IActiveX
{
[DispId(1)]
bool Initialize();
[DispId(2)]
bool Close();
}
//This class is registered for COM
public class ActiveX: IActiveX
{
MainWindow mainwindow;
Thread thread;
[STAThread]
public bool Initialize()
{
try
{
ThreadStart exeFunc = new ThreadStart(() =>
{
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
{
try
{
mainwindow = new MainWindow();
mainwindow.OpenWindow(); //OpenWindow() is the API of the MainApplication
}
catch()
{}
}));
});
thread = new Thread(exeFunc);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
System.Threading.Thread.Sleep(5000);
return true;
}
catch (Exception e)
{
return false;
}
}
public bool Close()
{
try
{
//Application.Current.Shutdown();
//Environment.Exit(0);
success = form.CloseWindow(); //CloseWindow() is the API of the MainApplication
Thread.Sleep(2000);
//thread.Join(15000);
//thread.Abort();
//thread = null;
//mainwindow = null;
GC.Collect();
Thread.Sleep(5000);
return success;
}
catch (Exception exp)
{
return false;
}
}
MainApplication APIs:
public bool OpenWindow()
{
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
{
try
{
this.ShowDialog();
}
catch()
{}
}));
return true;
}
public bool CloseWindow()
{
Dispatcher.Invoke(DispatcherPriority.Render, new Action(() =>
{
try
{
this.Close();
Application.Current.Shutdown();
}
catch
{}
}));
return true;
}
Related
I've got a WPF RichTextBox that I'd like to get working as a log output for the app.
I have a static class Log with method to write to the WPF RTB. Of course, this doesnt work when a background thread call the method.
I've tried using BeginInvoke, which works until the app gets closed throwing an error 'System.Windows.Application.Current.get returned null'
What is the proper approach to updating WPF RichText from other threads. And further, I dont think this background thread is disposing properly, any recommendations?
public partial class MainWindow : Window
{
Worker worker = new Worker();
public MainWindow()
{
InitializeComponent();
Log.rtb_control = rtbLog; // pass RTB ref to Log
worker.Start();
}
}
public static class Log
{
public static RichTextBox rtb_Control;
public static void Add(string Text)
{
App.Current.Dispatcher.BeginInvoke((Action)(() =>
{
rtb_Control.AppendText($"{Text}\r");
}
}
}
public class Worker
{
bool _Enabled = false;
public Worker()
{
_Manager = new Thread(new ThreadStart(Thread_Manager));
_Manager.Start();
}
public void Start()
{
_Enabled = true;
}
void Thread_Manager()
{
while(true)
{
if(_Enabled) { Log.Add("Inside Thread"); }
Thread.Sleep(10000);
}
}
}
I'm looking for a way to close a form from a background thread.
The scenario:
it's a chat application with a thread in background to manage the tcp client
now i want to close the first form from this thread
App.xaml.cs
public List<Window> dialogs = new List<Window>();
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Login loginDialog = new Login();
GUI.MainWindow mainDialog = new GUI.MainWindow();
dialogs.Add(loginDialog);
dialogs.Add(mainDialog);
client = new Klassen.TClient(dialogs);
if (loginDialog.ShowDialog() != true)
return;
}
the TClient class
public class TClient
{
public TSocket socket;
public TClient(List<Window> dialogs)
{
socket = new TSocket(dialogs);
}
}
the TSocket class, with the background thread
public class TSocket
{
/* Variables */
List<Window> dialogs;
public TSocket(List<Window> dialogs)
{
this.dialogs = dialogs;
clientThread = new Thread(connectionWorker);
clientThread.Start();
}
public bool connect()
{
/* Connect */
}
void connectionWorker()
{
connect();
while (isConnected)
{
/* if statment */
Login loginDialog = (Login)dialogs[0];
//dialogs[1].Close();
}
}
}
i already tried to work with a delagate and invoke , but it didn't worked properly
Windows programming allows only working with main UI thead for UI operations.
static class UiUtils
{
static UiUtils()
{
Dispatcher = Application.Current == null
? null
: Application.Current.Dispatcher;
}
public static Dispatcher Dispatcher { get; private set; }
public static void InvokeMainThread(this Action action)
{
try
{
if (Dispatcher != null && !Dispatcher.CheckAccess())
Dispatcher.Invoke(action);
else
action();
}
catch(Exception ex)
{
Debug.WriteLine("Error invoking main thread: {0}", ex);
}
}
}
And in your code you should call from any thread:
UiUtils.InvokeMainThread(()=>{loginDialog.Close();});`
I have a method that send some SMS to our customers that look like below:
public void ProccessSmsQueue()
{
SmsDbContext context = new SmsDbContext();
ISmsProvider provider = new ZenviaProvider();
SmsManager manager = new SmsManager(context, provider);
try
{
manager.ProcessQueue();
}
catch (Exception ex)
{
EventLog.WriteEntry(ex.Message, EventLogEntryType.Error);
}
finally
{
context.Dispose();
}
}
protected override void OnStart(string[] args)
{
Task.Factory.StartNew(DoWork).ContinueWith( ??? )
}
So, I have some issues:
I don´t know how long it takes for the method run;
The method can throw exceptions, that I want to write on EventLog
I want to run this method in loop, every 10 min, but only after last execution finish.
How I can achieve this? I thought about using ContinueWith(), but I still have questions on how to build the entire logic.
You should have an async method that accepts a CancellationToken so it knows when to stop, calls ProccessSmsQueue in a try-catch block and uses Task.Delay to asynchronously wait until the next time it needs to run:
public async Task DoWorkAsync(CancellationToken token)
{
while (true)
{
try
{
ProccessSmsQueue();
}
catch (Exception e)
{
// Handle exception
}
await Task.Delay(TimeSpan.FromMinutes(10), token);
}
}
You can call this method when your application starts and Task.Wait the returned task before existing so you know it completes and has no exceptions:
private Task _proccessSmsQueueTask;
private CancellationTokenSource _cancellationTokenSource;
protected override void OnStart(string[] args)
{
_cancellationTokenSource = new CancellationTokenSource();
_proccessSmsQueueTask = Task.Run(() => DoWorkAsync(_cancellationTokenSource.Token));
}
protected override void OnStop()
{
_cancellationTokenSource.Cancel();
try
{
_proccessSmsQueueTask.Wait();
}
catch (Exception e)
{
// handle exeption
}
}
Sample Worker Class that I have used in Windows Services. It supports stopping in a 'clean' way by using a lock.
You just have to add your code in DoWork, set your timer in the StartTimerAndWork method (in milliseconds), and use this class in your service.
public class TempWorker
{
private System.Timers.Timer _timer = new System.Timers.Timer();
private Thread _thread = null;
private object _workerStopRequestedLock = new object();
private bool _workerStopRequested = false;
private object _loopInProgressLock = new object();
private bool _loopInProgress = false;
bool LoopInProgress
{
get
{
bool rez = true;
lock (_loopInProgressLock)
rez = _loopInProgress;
return rez;
}
set
{
lock (_loopInProgressLock)
_loopInProgress = value;
}
}
#region constructors
public TempWorker()
{
}
#endregion
#region public methods
public void StartWorker()
{
lock (_workerStopRequestedLock)
{
this._workerStopRequested = false;
}
_thread = new Thread(new ThreadStart(StartTimerAndWork));
_thread.Start();
}
public void StopWorker()
{
if (this._thread == null)
return;
lock (_workerStopRequestedLock)
this._workerStopRequested = true;
int iter = 0;
while (LoopInProgress)
{
Thread.Sleep(100);
iter++;
if (iter == 60)
{
_thread.Abort();
}
}
//if (!_thread.Join(60000))
// _thread.Abort();
}
#endregion
#region private methods
private void StartTimerAndWork()
{
this._timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
this._timer.Interval = 10000;//milliseconds
this._timer.Enabled = true;
this._timer.Start();
}
#endregion
#region event handlers
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if (!LoopInProgress)
{
lock (_workerStopRequestedLock)
{
if (this._workerStopRequested)
{
this._timer.Stop();
return;
}
}
DoWork();
}
}
private void DoWork()
{
try
{
this.LoopInProgress = true;
//DO WORK HERE
}
catch (Exception ex)
{
//LOG EXCEPTION HERE
}
finally
{
this.LoopInProgress = false;
}
}
#endregion
}
This question already has answers here:
How can I make the cursor turn to the wait cursor?
(11 answers)
Closed 9 years ago.
I have a Windows Forms application, in my application i load files into a list box and sometimes this could take few seconds so in this time i want to show "Spinning Wheel” and i found this Gif: http://www.ajaxload.info/
is it possible to add it to my application while my application is busy over the controllers ?
Yes
Found some old code from a project where I had it.
Edited out a few things, you should be able to get it working easily.
Invoke it:
GuiCursor.WaitCursor(() => { yourclass.DoSomething(); });
The class
internal class GuiCursor
{
private static GuiCursor instance = new GuiCursor();
private GuiCursor() { }
static GuiCursor() { }
internal static void WaitCursor(MethodInvoker oper)
{
if (Form.ActiveForm != null && !Thread.CurrentThread.IsBackground)
{
Form myform = Form.ActiveForm;
myform.Cursor = Cursors.WaitCursor;
try
{
oper();
}
finally
{
myform.Cursor = Cursors.Default;
}
}
else
{
oper();
}
}
internal static void ToggleWaitCursor(Form form, bool wait)
{
if (form != null)
{
if (form.InvokeRequired)
{
form.Invoke(new MethodInvoker(() => { form.Cursor = wait? Cursors.WaitCursor : Cursors.Default; }));
}
else
{
form.Cursor = wait ? Cursors.WaitCursor : Cursors.Default;
}
}
}
internal static void Run(Form form)
{
try
{
Application.Run(form);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
As by request, an example. Create a new winform project to test it out.
As default you get a Form1. Add a button to it, double click on it so you get a autogenerated method to it.
Replace the class Form1 with this.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
GuiCursor.WaitCursor(() => { DoSomething(); });
}
private void DoSomething()
{
Thread.Sleep(3000);
}
}
internal class GuiCursor
{
private static GuiCursor instance = new GuiCursor();
private GuiCursor() { }
static GuiCursor() { }
internal static void WaitCursor(MethodInvoker oper)
{
if (Form.ActiveForm != null && !Thread.CurrentThread.IsBackground)
{
Form myform = Form.ActiveForm;
myform.Cursor = Cursors.WaitCursor;
try
{
oper();
}
finally
{
myform.Cursor = Cursors.Default;
}
}
else
{
oper();
}
}
internal static void ToggleWaitCursor(Form form, bool wait)
{
if (form != null)
{
if (form.InvokeRequired)
{
form.Invoke(new MethodInvoker(() => { form.Cursor = wait ? Cursors.WaitCursor : Cursors.Default; }));
}
else
{
form.Cursor = wait ? Cursors.WaitCursor : Cursors.Default;
}
}
}
internal static void Run(Form form)
{
try
{
Application.Run(form);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
A little trick to do this could be to use a PictureBox with image in it. On button click, make the PictureBox visible and hide it again after click operation is completed.
I want to know how to stop and restart a thread.
I create N amount of threads, depending on conditions returned from a database. These are long running processes which should never stop but should I get a critical error within the thread I want to completely kill the thread and start it up like new.
The code which I use currently to start the threads:
foreach (MobileAccounts MobileAccount in ReceiverAccounts)
{
Receiver rec = new Receiver();
ThreadStart starterParameters = delegate { rec.StartListener(MobileAccount); };
Thread FeedbackThread = new Thread(starterParameters);
FeedbackThread.Name = MobileAccount.FriendlyName;
FeedbackThread.Start();
Thread.Sleep(1000);
}
You can write your own listener and manage its thread within it.
something like:
public class AccountListener
{
private Thread _worker = null;
private MobileAccount _mobileAccount;
public AccountListener(MobileAccount mobileAccount)
{
_mobileAccount = mobileAccount;
}
protected void Listen()
{
try
{
DoWork();
}
catch (Exception exc)
{
}
}
protected virtual void DoWork()
{
Console.WriteLine(_mobileAccount);
}
public void Start()
{
if (_worker == null)
{
_worker = new Thread(Listen);
}
_worker.Start();
}
public void Stop()
{
try
{
_worker.Abort();
}
catch (Exception)
{
//thrad abort exception
}
finally
{
_worker = null;
}
}
}