C# Thread Abort Occur 'Safe Handle been Closed' - c#

I have three class, Main, UserSerial, Communication
In Main
Communication Comm;
Thread CoTH;
UserSerial Serial;
private void btnStart_Click(object sender, EventArgs e)
{
CoTH = new Thread(() =>
{
commJob();
});
CoTH.Start();
}
private void commJob()
{
Serial.Setting();
Serial.Open();
Comm = new Communication(Serial);
Comm.StartConnection();
}
In Communication
UserSerial Serial;
public Communication(UserSerial Serial)
{
this.Serial = Serial;
}
public void Read()
{
lock(Serial.Synchronous)
{
while(condition...)
{
Serial.Receive();
// ....
}
}
}
And UserSerial is not my code, so I don't know detail..
Anyway, When I want serial communication force terminate, I Use Thread.Abort() in Main.
private void btnStop_Click(object sender, EventArgs e)
{
try
{
if (Serial != null)
Serial.Close();
if (CoTH != null)
CoTH.Abort();
}
catch
{
}
}
But sometimes it occur 'Safe Handle been Closed', so program is abnormal termination.
How Can I communication force terminate without 'Safe Handle been Closed'?

It seems you should stop CoTH first and then Serial. Or you will brutally terminate CoTH since it's using Serial while not knowing it has been disposed.
In your class Communication. It's keep calling Serial.Receive().
public void Read()
{
lock(Serial.Synchronous)
{
while(condition...)
{
Serial.Receive();
// ....
}
}
}
However your Stop method is disposing resource Serial before closing the communication logic CoTH.
if (Serial != null)
Serial.Close();
if (CoTH != null)
CoTH.Abort();
You close Serial first. What if Communication.Read() wants to call Serial.Receive() after you closed it?
My suggestion:
Let Communication handle the resource, or a supervisor take care of their construction and destruction.

Related

How to forcefully abort thread created by BackgroundWorker without using DoWorkEventArgs Cancel property?

I have one third party dll without source-code which accept file pages array and return book object. That dll have one function GenerateBook(Page[] pages), which execute under BackgroungWorker.
If user press abort button, process should stop generating book. Using cancelAsync(), I can send cancel request to BackgroundWorker thread process. But GenerateBook(Page[] pages) is third party function, so I can't use e.cancel inside that.
Now In this scenario, How to abort background worker process immediately? Please give me suggestion. Right now I am using below code. but that is not working.
public class AbortableBackgroundWorker : BackgroundWorker
{
public delegate void ErrorEventHandler(string message, ReportRunStatus status);
public event ErrorEventHandler foundError;
public Thread workerThread { get; set; }
private bool isFromAbort;
protected override void OnDoWork(DoWorkEventArgs e)
{
workerThread = Thread.CurrentThread;
try
{
base.OnDoWork(e);
}
catch (Exception ex)
{
if (!isFromAbort)
{
if (foundError != null)
foundError(ex.Message.ToString(), ReportRunStatus.Error);
}
e.Cancel = true;
this.Dispose();
}
}
public void Abort()
{
if (workerThread != null)
{
isFromAbort = true;
workerThread.Abort();
workerThread = null;
}
}
}
You may try using asynchronous call using BeginInvoke and EndInvoke. One of the given methods in the reference link should solve the issue.
https://support.microsoft.com/en-us/help/315582/how-to-call-a-visual-c-method-asynchronously

Best Practices: C# working with DB

First of all, I'm Java programmer and I'm new on C# and I need opinion of C# developers. I'm developing an application that connecting to database (firebird 1.5), query some data and return to me so there's nothing to be complicated but unfortunately I've stuck in some things :
As we know the database connection should be realised in separate thread cause it's a highweight operation and all the connections should be in connection pool in order to reuse already opened connection instead create the new one.
So here go my first question - how to organize connection pool properly?
(What about connection pool I've read that usually connection pool is already realised by data providers and I can just set it in connection parametres someway like "connectionBuilder.Pooling = true;")
What about queries? I mean that I've always use a Query per-Thread (and I think that is right cause we also do a highweight operation, am I wrong? Anyway I'd glad to see your best practices with organizing database work) and in Java I just do return Query result from separate thread by use an interfaces and anonymous classes like this:
In DBHelper.class (DBHelper is a singleton)
public interface QueryListener {
public void onSuccess(ArrayList<?>);
public void onError(Exception e);
}
public synchronized void getPromoActions(final QueryListener listener) {
if (listener != null) {
try {
ArrayList<String> myPromoActions;
.............
// some query's code
.....
listener.onSucces(myPromoActions);
} catch(Exception e) {
listener.onError(e);
} finally {
closeDatabase();
}
}
}
in some UI-class (for eaxample MainWindow)
public void getPromoActions(){
new Thread(new Runnable() {
#Override
public void run() {
DBHelper.getInstance().getPromoActions(new QueryListener() {
#Override
public void onSuccess(ArrayList<?>) {
// set Data to UI element such as Table
}
#Override
public void onError(Exception e){
// Handling exception
}
});
}
}).start();
}
In C# I should use delegates to mark which method will execute in thread, but unfortionally I can't send any callback as parameter - so how I should return my Query results to main UI thread?
UPD
I've understand a little bit how to work with delegates and events but have a problem with raising a custom event. I had declared an EventHandler and an custom EventArgs:
public delegate void QueryResultEventHandler(object sender, QueryResultEventArgs e);
public class QueryResultEventArgs : EventArgs
{
public List<String> QueryResult { get; set; }
public int QueryRecordsCount { get; set; }
}
And in My DBHelper.class I declared a next field and event:
private QueryResultEventHandler _queryResult;
public event QueryResultEventHandler onQueryResult
{
add
{
lock (this)
{
_queryResult += value;
}
}
remove
{
lock (this)
{
_queryResult -= value;
}
}
}
In UI class (MainWindow) I use next code:
public void GetAllDistricts() {
DBHelper.Instance.onQueryResult += new QueryResultEventHandler(GetAllDistricsResultHandler);
DBHelper.Instance.GetAllDistricts();
}
public void GetAllDistricsResultHandler(object sender, QueryResultEventArgs e){
// Here I'm adding the query result to Table
}
So my problem now is a how to raise an event asynchronously? In my DBHelper.class I'm trying to use beginInvoke&endInvoke with _query delegate but it seems that I had missed some code lines whatever it was I can't understand what I'm doing wrong an how to raise event asynchronously? Here my DBHelper.class code:
public void GetAllDistricts() {
try
{
if (_queryResult != null)
{
//** This code should run asynchronously ---------->
using (FbConnection connection = GetConnection())
{
FbCommand getAllDistrictsCommand = new FbCommand();
getAllDistrictsCommand.CommandText = "SELECT * FROM SEND";
getAllDistrictsCommand.Connection = connection;
QueryResultEventArgs args = new QueryResultEventArgs();
using (FbDataReader reader = getAllDistrictsCommand.ExecuteReader())
{
while (reader.Read())
{
//Here must be the processing of query results and filling the
//QueryResultEventArgs
args.QueryResult.Add(reader[0].ToString());
}
args.QueryRecordsCount = reader.GetInt32(reader.GetOrdinal("Rows"));
// And here after sucessfull query I should call OnQueryResult()
OnQueryResult(args);
}
}
//**<--------------------
}
else
{
throw new Exception("...Some exception message...");
}
}
catch (Exception e)
{
log.ErrorException(e.Message, e);
throw new Exception("...Some exception message...");;
}
finally {
CloseConnection();
}
}
// The QueryResultEvent method
protected void OnQueryResult(QueryResultEventArgs e)
{
if (_queryResult != null)
{
_queryResult(this, e);
}
}
First about connection pooling. If you will use ADO.NET then you do not need to worry about that, because it's already there. You don't need to do any extra work, you just create a connection:
using (var connection = new SqlConnection(connectionString))
{
// Queries to DB
}
You should always Close or Dispose you connections. The names of the methods look "scary" but actually connections are reused. Please read this MSDN article to get more details.
The code you proposed looks over-complicated. I think you should consider using async/await pattern which is in general not multithreaded, but it handles UI responsiveness issues and simplifies writing/reading of the code. In newer versions of .NET almost all methods that are potentially long to execute has async versions. So for example your data access layer might look like that (I'm using Dapper ORM's QueryAsync method just to keep code short and simple):
public async Task<IList<District>> GetAllDistrictsAsync()
{
using (var connection = await GetConnectionAsync())
{
return (await connection.QueryAsync<District>("select * from Districts")).ToList();
}
}
public async Task<IDbConnection> GetConnectionAsync()
{
var connectionString =
ConfigurationManager.ConnectionStrings["DbConnectionString"].ConnectionString;
var connection = new SqlConnection(connectionString);
await connection.OpenAsync();
return connection;
}
And then somewhere on UI:
private async void Button_Click(object sender, EventArgs e)
{
var districts = await GetAllDistrictsAsync();
}
If you still need to execute some code in different thread you should look at Tasks namespace.
Task.Factory
.StartNew<IList<District>>(GetAllDistricts)
.ContinueWith(districts =>
{
// UI thread
}, TaskScheduler.FromCurrentSynchronizationContext());
In this example GetAllDistricts is not async and is executed in different thread. But ContinueWith will be executed in UI thread because of TaskScheduler.FromCurrentSynchronizationContext().
public void GetAllDistricts() {
DBHelper.Instance.onQueryResult +=
new QueryResultEventHandler(GetAllDistricsResultHandler);
new Thread(
new ThreadStart(DBHelper.Instance.GetAllDistricts)
).Start();
}
But the problem you will face is that you won't be able to access your UI controls from the EventHandler as it will be denied because you are not in the same thread anymore...
Refer to that article for some explanation
How to update the GUI from another thread in C#?
To avoid this you can maybe use the BackgroundWorker control.
Use this option
http://www.asp.net/mvc/overview/older-versions-1/models-(data)/creating-model-classes-with-the-entity-framework-cs
it is easy to use and easy to database operation with less code.

How to receive data with ZeroMQ?

I have a simple application which sends and receives data.
ZSocketExample client = new ZSocketExample("127.0.0.1:5555");
client.send("test");
This is my client class:
public class ZSocketExample:IDisposable
{
public delegate void ReceiveEventHandler(object sender, SocketEventArgs e);
public event ReceiveEventHandler ReceiveEvent;
private ZmqContext zmqContext;
private ZmqSocket zmqSocket;
private string host;
private bool isRunning;
private bool disposed = false;
public ZSocketExample(string host)
{
try
{
zmqContext = ZmqContext.Create();
zmqSocket = zmqContext.CreateSocket(SocketType.DEALER);
ZHelpers.SetID(zmqSocket, Encoding.UTF8);
zmqSocket.Connect(host);
this.isRunning = true;
zmqSocket.ReceiveReady += new EventHandler<SocketEventArgs>(zmqSocket_ReceiveReady);
zmqSocket.SendReady += new EventHandler<SocketEventArgs>(zmqSocket_SendReady);
Poller poller = new Poller(new List<ZmqSocket> { zmqSocket });
while (isRunning)
{
poller.Poll(TimeSpan.FromSeconds(5));
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
void zmqSocket_ReceiveReady(object sender, SocketEventArgs e)
{
Console.WriteLine("Receive Ready");
}
void zmqSocket_SendReady(object sender, SocketEventArgs e)
{
Console.WriteLine("Send Ready");
}
public void send(string msg)
{
zmqSocket.Send(msg, Encoding.UTF8);
if (ReceiveEvent != null)
ReceiveEvent(this, null);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
close();
}
disposed = true;
}
public void close()
{
isRunning = false;
zmqSocket.Linger = TimeSpan.FromSeconds(1);
zmqSocket.Close();
zmqContext.Terminate();
}
}
But somehow it doesnot send or receive. Can someone tell me what do I do wrong? And this example blocks the main application. how can I make it non blocking?
ZeroMQ socket is not thread safe, you can't use it from multiple threads without using some kind of synchronization.
In your example you call the close which set a variable and then immediately close the socket, this is wrong, you should close the socket when you are out of the while loop.
Regarding receive/send ready, you rarely need to register for send ready, send ready will let you know when you can send a message, in the dealer socket if you are connected you always will be ready to send (unless the highwater has reached).
Receive Ready will be invoked when there is message ready to be received, if other side send you a message the receive ready will be invoked.
For the last part, blocking, you need a dedicate thread to handle zeromq sockets, you can have one thread that handle multiple sockets using the poller.

C# TcpSockets Do I disconnect the clean/proper way?

So i know there are a lot of articles out there on this topic and i did read a lot of them i would say but for some reason im sure my code is not doing what it is supposed to do.
I want to close a connection between my Server and my Client.
Now on the serverside i start the disconnect with this code
public void shutdown()
{
_socket.Shutdown(SocketShutdown.Both);
_socket.Close();
}
And on the Client side i have some troubles understanding how i get to the disconnect what i believe is happening is the following: in my async receive callback i should get an error since the server started a shutdown sequence and i have to handle that (right???) so my code for the client looks like this:
ReceiveCallback:
private void ReceiveCallback(IAsyncResult result)
{
int bytesRecieved = 0;
byte[] tempBuff;
//Try to receive But if a Socket error occures disconnect otherwise start Receiving again
try
{
bytesRecieved = _socket.EndReceive(result);
}
catch (SocketException sockEx)
{
Disconnect(sockEx);
return;
}
catch (ObjectDisposedException disposeEx)
{
Disconnect(disposeEx);
return;
}
catch (Exception ex)
{
StartReceive();
return;
}
if (bytesRecieved == 0)
{
StartReceive();
return;
}
tempBuff = new byte[bytesRecieved];
Buffer.BlockCopy(_buffer, 0, tempBuff, 0, bytesRecieved);
StartReceive();
_packHandler.handlePacket(tempBuff);
}
Disconnect:
public void Disconnect()
{
if (!_socket.Connected)
{
return;
}
_socket.BeginDisconnect(false, DisconnectCallback, null);
}
DisconnectCallback
private void DisconnectCallback(IAsyncResult result)
{
_socket.EndDisconnect(result);
_socket.Close();
}
(The Disconnect Method is overloaded so if i get an exception it puts up a messageBox and then also calls Disconnect. Just so i know what happened.)
Where am i wrong and what can i improve uppon ???
I tried the code and it seemed to work but i then looked with netstat if all sockets are closed and the client socket was not. It was in FIN_WAIT_2 which means that it (or the server???) did not yet send the FIN packet right ?
Oh and then i tried it again with this line changed:
if (bytesRecieved == 0)
{
StartReceive();
return;
}
TO
if (bytesRecieved == 0)
{
Disconnect;
return;
}
which then threw an exception on the serverside and on the clientside the client said that the connection was closed by the server ???
EDIT: Even when i have closed both Programs Netstat still shows the port in a WAITING status. what does that tell me ?
Your normal disconnect has a shutdown which will clear the socket so it can disconnect properly but your async style never calls shutdown. I added it in a convenient location below.
public void Disconnect()
{
if (!_socket.Connected)
{
return;
}
_socket.Shutdown(SocketShutdown.Both); // Make sure to do this
_socket.BeginDisconnect(false, DisconnectCallback, null);
}
EDIT:
From the sounds of it you don't have a reason to be using the Async Method? The async methods are so you can send data in a separate execution thread freeing up your thread to do some data processing for instance while that occurs.
I don't see any processing going on so I suggest you change disconnect like this and see if it resolves the problem. Because I don't think you are waiting on the Async methods which will not work out well.
public void Disconnect()
{
if (!_socket.Connected)
{
return;
}
shutdown(); //Your standard disconnect that you showed up top. Scoping might be required.
}
A bit of data on Async can be scrounged up here: http://msdn.microsoft.com/en-us/library/38dxf7kt(v=vs.110).aspx
Important is:
If a server starts a shutdown sequence you DO have to handle it
Both sides have to call shutdown on their socket
You need a way to notice the disconnect (it does not give you an error, or least it didnt for me)
Therefor I created my own class customSocket which inherits from Socket
public class customSocket : Socket
{
#region Properties
private readonly Timer _timer;
private const int _interval = 1000;
private bool Connected
{
get
{
bool part1 = Poll(1000, SelectMode.SelectRead);
bool part2 = (Available == 0);
if (part1 && part2)
return false;
else
return true;
}
}
public bool EventsEnabled
{
set
{
if (value)
{
_timer.Start();
}
else
_timer.Stop();
}
}
#endregion
#region Constructors
public customSocket(AddressFamily addressFamily, SocketType sockType, ProtocolType protocolType)
: base(addressFamily, sockType, protocolType)
{
_timer = new Timer { Interval = _interval };
_timer.Elapsed += TimerTick;
}
public customSocket(SocketInformation sockInfo)
: base(sockInfo)
{
_timer = new Timer { Interval = _interval };
_timer.Elapsed += TimerTick;
}
#endregion
#region Events
public event EventHandler<EventArgs> Socket_disconected;
public void Raise_Socket_disconnected()
{
EventHandler<EventArgs> handler = Socket_disconected;
if (handler != null)
{
handler(this,new EventArgs());
}
}
private void TimerTick(object sender, EventArgs e)
{
if (!Connected)
{
Raise_Socket_disconnected();
}
}
#endregion
}
This version of a socket has an Event for a disconnect.
Now if you create an instance of your socket class you have to connect the handler and set the EventsEnabled true.
This handler then calls the shutdown and your socket does not stay in FIN_WAIT_2

How can I listen to this event on a different thread?

I've made a little test program to try and get a USB card reader working using an ActiveX control provided by the manufacturer.
The form works fine as long as it doesn't use a separate thread. I create a new instance of Reader and listen to the Read event and everything works fine. I swipe a card, the event fires and the textbox gets updated.
private Reader _reader;
public Form1()
{
InitializeComponent();
CreateScanner();
}
public void CreateScanner()
{
_reader = new Reader();
_reader.Read += Read;
}
void Read(object sender, EventArgs e)
{
CardData.Text = "Card Read";
}
Reader class in case it helps:
public class Reader
{
private AxUSBHIDInsert _axUsbHid;
public event EventHandler Read;
public Reader()
{
_axUsbHid = new AxUSBHIDInsert();
_axUsbHid.CreateControl();
_axUsbHid.BeginInit();
_axUsbHid.MSRReadDir = MSRReadDirection.ReadWithdrawal;
_axUsbHid.EndInit();
_axUsbHid.PortOpen = true;
_axUsbHid.CardDataChanged += CardDataChanged;
}
void CardDataChanged(object sender, EventArgs e)
{
if (Read != null)
Read(this, new EventArgs());
}
}
However, I need to run this on a separate thread. So I change the constructor to be
Thread thread = new Thread(CreateScanner);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
It has to be an STA thread otherwise the ActiveX control will complain that it cannot be instantiated. However doing this, the event doesn't fire anymore. I'm not that familiar with how threading works, so I'm not sure why.
Any ideas? Note that it has to work this way (separate thread, hooked up to the Read event), because the code will eventually reside in a class library that gets deployed with an application that I cannot change.
Your COM object sends messages to the second thread, that means it must be alive all the time application is running.
Try to do like this:
public class Reader
{
public Reader()
{
// leave empty
}
public Read() {
_axUsbHid = new AxUSBHIDInsert();
...
}
}
public Form1()
{
InitializeComponent();
_reader = new Reader();
_reader.Read += Read;
StartRead(_reader);
}
void StartRead(Reader reader) {
Thread thread = new Thread(ReadRoutine);
thread.SetApartmentState(ApartmentState.STA);
thread.Start(reader);
}
void ReadRoutine(object param) {
Reader reader = (Reader)param;
reader.Read();
while (AppIsAlive) { // add logic here
// bad code, import GetMessage from user32.dll
Application.DoEvents();
Thread.Sleep(100);
}
}
But the Read event must be processed synchronously:
void Read(object sender, EventArgs e)
{
if (this.InvokeRequired)
this.BeginInvoke(new EventHandler(Read), new object[2] { sender, e } );
else {
CardData.Text = "Card Read";
}
}

Categories

Resources