C# TcpListener.BeginAccept and ObjectDisposedException - multithreading

I encounter the ugly socket management pattern in C# where I have to catch an exception when I want to stop or close a socket...
I would like to handle my sockets so the ObjectDisposedException don't pop!
I was wondering if this code would be ok
private TcpListener server;
private bool listening;
private void Initialize() {
this.listening = true;
this.server = new TcpListener(ip, port);
this.server.BeginAcceptTcpClient(this.AcceptSocket, null);
}
private void AcceptSocket(IAsyncResult result) {
if (listening) this.server.EndAcceptTcpListener(result);
else ; //Nothing or maybe some cleaning if necessary?
}
private void StopListening() {
this.listening = false;
this.server.Stop();
}
As you may know, the Stop method will trigger the AsyncCallback "AcceptSocket" while the underlying socket is closed so an ObjectDisposedException will be thrown if EndAcceptTcpListener is called...
Here, EndAcceptTcpListener is never called if the callback is triggered by a TcpListener.Stop!
So, I would like to know what happens if I don't call EndAcceptTcpListener since msdn says I MUST do it but I say I DON'T WANT that ugly exception if I can prevent it!
If it's really required to EndAccept I would like to know if you have a solution to manage socket stop and close whose avoid that stupid exception!!

Related

javamail idle stops triggering messagesAdded after a while, thread locked

I'm developing an android app that receives and processes mail messages. The app must be connected to an IMAP server and keep the connection alive, so it can see and process new mail messages instantly (mails contains json data from a mail api server). The app have two modes, manual and live connection. Here is some of my code:
class Idler {
Thread th;
volatile Boolean isIdling=false;
boolean shouldsync=false;//we need to see if we have unseen mails
Object idleLock;
Handler handler=new Handler();
IMAPFolder inbox;
public boolean keppAliveConnection;//keep alive connection, or manual mode
//This thread should keep the idle connection alive, or in case it's set to manual mode (keppAliveConnection=false) get new mail.
Thread refreshThread;
synchronized void refresh()
{
if(isIdling)//if already idling, just keep connection alive
{
refreshThread =new Thread(new Runnable() {
#Override
public void run() {
try {
inbox.doCommand(new IMAPFolder.ProtocolCommand() {
#Override
public Object doCommand(IMAPProtocol protocol) throws ProtocolException {
//Why not noop?
//any call to IMAPFolder.doCommand() will trigger waitIfIdle, this
//issues a "DONE" command and waits for idle to return(ideally with a DONE server response).
// So... I think NOOP is unnecessary
//protocol.simpleCommand("NOOP",null); I'm not issuing noop due to what I said ^
//PD: if connection was broken, then server response will never arrive, and idle will keep running forever
//without triggering messagesAdded event any more :'( I see any other explanation to this phenomenon
return null;
}
});
} catch (MessagingException e) {
e.printStackTrace();
}
}
},"SyncThread");
refreshThread.start();
}
else
{
getNewMail();//If manual mode keppAliveConnection=false) get the new mail
}
}
public Idler()
{
th=new Thread(new Runnable() {
#SuppressWarnings("InfiniteLoopStatement")
#Override
public void run() {
while (true)
{
try {
if(refreshThread !=null && refreshThread.isAlive())
refreshThread.interrupt();//if the refresher thread is active: interrupt. I thing this is not necessary at this point, but not shure
initIMAP();//initializes imap store
try {
shouldsync=connectIMAP()||shouldsync;//if was disconnected or ordered to sync: needs to sync
}
catch (Exception e)
{
Thread.sleep(5000);//if can't connect: wait some time and throw
throw e;
}
shouldsync=initInbox()||shouldsync;//if inbox was null or closed: needs to sync
if(shouldsync)//if needs to sync
{
getNewMail();//gets new unseen mail
shouldsync=false;//already refreshed, clear sync "flag"
}
while (keppAliveConnection) {//if sould keep idling "forever"
synchronized (idleLock){}//MessageCountListener may be doing some work... wait for it
isIdling = true; //set isIdling "flag"
handler.removeCallbacksAndMessages(null);//clears refresh scheduled tasks
handler.postDelayed(new Runnable() {
#Override
public void run() {
refresh();
}
},1200000);//Schedule a refresh in 20 minutes
inbox.idle();//start idling
if(refreshThread !=null && refreshThread.isAlive())
refreshThread.interrupt();//if the refresher thread is active: interrupt. I thing this is not necessary at this point, but not shure
handler.removeCallbacksAndMessages(null);//clears refresh scheduled tasks
isIdling=false;//clear isIdling "flag"
if(shouldsync)
break;//if ordered to sync... break. The loop will handle it upstairs.
synchronized (idleLock){}//MessageCountListener may be doing some work... wait for it
}
}
catch (Exception e) {
//if the refresher thread is active: interrupt
//Why interrupt? refresher thread may be waiting for idle to return after "DONE" command, but if folder was closed and throws
//a FolderClosedException, then it could wait forever...., so... interrupt.
if (refreshThread != null && refreshThread.isAlive())
refreshThread.interrupt();
handler.removeCallbacksAndMessages(null);//clears refresh scheduled tasks
}
}
}
},"IdlerThread");
th.start();
}
private synchronized void getNewMail()
{
shouldsync=false;
long uid=getLastSeen();//get last unprocessed mail
SearchTerm searchTerm=new UidTerm(uid,Long.MAX_VALUE);//search from las processed message to the las one.
IMAPSearchOperation so=new IMAPSearchOperation(searchTerm);
try {
so.run();//search new messages
final long[] is=so.uids();//get unprocessed messages count
if (is.length > 0) {//if some...
try {
//there are new messages
IMAPFetchMessagesOperation fop=new IMAPFetchMessagesOperation(is);
fop.run();//fetch new messages
if(fop.messages.length>0)
{
//process fetched messages (internally sets the last seen uid value & delete some...)
processMessages(fop.messages);
}
inbox.expunge();//expunge deleted messages if any
}
catch (Exception e)
{
//Do something
}
}
else
{
//Do something
}
}
catch (Exception e)
{
//Do something
}
}
private synchronized void initIMAP()
{
if(store==null)
{
store=new IMAPStore(mailSession,new URLName("imap",p.IMAPServer,p.IMAPPort,null,p.IMAPUser,p.IMAPPassword));
}
}
private boolean connectIMAP() throws MessagingException {
try {
store.connect(p.IMAPServer, p.IMAPPort, p.IMAPUser, p.IMAPPassword);
return true;
}
catch (IllegalStateException e)
{
return false;
}
}
//returns true if the folder was closed or null
private synchronized boolean initInbox() throws MessagingException {
boolean retVal=false;
if(inbox==null)
{//if null, create. This is called after initializing store
inbox = (IMAPFolder) store.getFolder("INBOX");
inbox.addMessageCountListener(countListener);
retVal=true;//was created
}
if(!inbox.isOpen())
{
inbox.open(Folder.READ_WRITE);
retVal=true;//was oppened
}
return retVal;
}
private MessageCountListener countListener= new MessageCountAdapter() {
#Override
public void messagesAdded(MessageCountEvent ev) {
synchronized (idleLock)
{
try {
processMessages(ev.getMessages());//process the new messages, (internally sets the last seen uid value & delete some...)
inbox.expunge();//expunge deleted messajes if any
} catch (MessagingException e) {
//Do something
}
}
}
};
}
The problem is: Sometimes when the user is refreshing or the app auto-refreshes, in the Alive Connection mode, one or both of this conditions keeps my app from getting new messages. This is from the javamail source code.
1: The IdlerThread enters monitor state in:
//I don't know why sometimes it enters monitor state here.
private synchronized void throwClosedException(ConnectionException cex)
throws FolderClosedException, StoreClosedException {
// If it's the folder's protocol object, throw a FolderClosedException;
// otherwise, throw a StoreClosedException.
// If a command has failed because the connection is closed,
// the folder will have already been forced closed by the
// time we get here and our protocol object will have been
// released, so if we no longer have a protocol object we base
// this decision on whether we *think* the folder is open.
if ((protocol != null && cex.getProtocol() == protocol) ||
(protocol == null && !reallyClosed))
throw new FolderClosedException(this, cex.getMessage());
else
throw new StoreClosedException(store, cex.getMessage());
}
2: The "refresherThread" enters wait state in:
void waitIfIdle() throws ProtocolException {
assert Thread.holdsLock(messageCacheLock);
while (idleState != RUNNING) {
if (idleState == IDLE) {
protocol.idleAbort();
idleState = ABORTING;
}
try {
// give up lock and wait to be not idle
messageCacheLock.wait();//<-----This is the line is driving me crazy.
} catch (InterruptedException ex) { }
}
}
As one of both of this threads "stops" running (wait & monitor state) my app is useless when reach this condition. In my country the mobile data network is very unstable, slow & expensive(GSM) So it must be failure resilient and take care about every transferred bit.
I guess the problem arises when the connection silently fails and the refresherThread starts to do its job. It issues a DONE command if idle is active, but, as the connection is gone, when idle tries to throw a FolderClosedException, one or both threads gets locked indefinitely.
So, my question is: Why is this situation arising and how to prevent it? How can I keep the idle loop securely running without getting locked?
I've tried a lot of things till exhaustion with no results.
Here are some threads I've read without getting a solution to my problem. In my country internet is EXTREMELY expensive too, so I can't research as much as I want, nor list all the urls I've visited looking for information.
JavaMail: Keeping IMAPFolder.idle() alive
JavaMail: Keeping IMAPFolder.idle() alive
Javamail : Proper way to issue idle() for IMAPFolder
Please, excuse my english. Any suggestion will be greatly appreciated. I've heard about this site strictness, so please be gentle, I'm new over here.
Be sure to set the timeout properties to make sure you don't hang waiting for a dead connection or server.
Instead of issuing a nop command directly, you should call Folder.isOpen or Folder.getMessageCount; they'll issue the nop command if needed.
If the folder is closed asynchronously (FolderClosedException), you'll need to restart the idle loop.

Java EventListener inside of SwingWorker

OK, so I'm a bit new to SwingWorker in Java.
I've built a Java GUI that, when the "Start" button is pressed, launches several SwingWorker threads. The first thread simply keeps track of run time and updates the GUI appropriately. The second one plays a series of sounds files. The third (and problematic) thread should monitor the serial port for incoming data to be manipulated later on down the road. All of these threads will be running for a while, hence them being SwingWorkers.
I am using the jSSC library (https://code.google.com/p/java-simple-serial-connector/wiki/jSSC_examples) to read data from the serial port, and it does so by firing an eventListener.
My question: Is it redundant/inelegant to code an EventListener inside of a SwingWorker thread? And if so, is there a better way to go about this?
Here is a bit of my code:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
SerialPort serialPort = findPort(); // returns a serialport I can use to read data from.
SwingWorker worker1 = new SwingWorker<Void, Void>(){
#Override
protected Void doInBackground() throws Exception {
long elapsedTime, startTime = System.currentTimeMillis();
while (true){
Thread.sleep(1000);
elapsedTime = (System.currentTimeMillis() - startTime)/1000;
jTimeField.setText(String.format("%02d:%02d:%02d", elapsedTime/3600, (elapsedTime%3600)/60, elapsedTime%60));
if (isCancelled()){} /* Check if thread has been canceled */
}
}
};
SwingWorker worker2 = new SwingWorker<Void, Void>(){
#Override
protected Void doInBackground() throws Exception {
// This Thread: Plays music files; Self terminates; On termination also terminates worker 1 and 3 via cancel().
}
};
SwingWorker worker3 = new SwingWorker<Void, Void>(){
#Override
protected Void doInBackground() throws Exception {
serialPort.addEventListener(new SerialPortReader());
return null;
}
class SerialPortReader implements SerialPortEventListener {
#Override
public void serialEvent(SerialPortEvent event) {
byte buffer[];
if (event.isRXCHAR() && event.getEventValue() > 0){
buffer = serialPort.readBytes();
for (byte b: buffer){
// Do stuff with incoming data
}
}
}
}
};
}
Any and all constructive criticism is appreciated.
It does not do any good to add the event listener in your swingworker thread and then return once that's done. Why not just add the listener from your EDT and, if it takes long to process events, fire off processing threads from there? Listening to events can't be blocking, that would defeat the entire Observer pattern.

J2ME thread programming

I am creating a j2me application which is interacting with a database on a server. Therefore I launch a thread to connect to the server. I handle all my command actions in a separate class which implements CommandListener.
When I try to get the response the server returned I get an empty String. I have tried waiting for the thread that connects to the server to return but this makes the application unresponsive.
Below is the code I am using.
//my network worker class.
public class NetworkConnector implements Runnable {
//constructor
public NetworkConnector(String url){
//url =>server url to connect to.
Thread thread = new Thread(this);
thread.start();
}
private String serverReply="";
private String url="
//method to connect to the server and return the
//response from the server.
public String sendData(String serverUrl) {
//open streams to connect to the Server.
httpConn = (HttpConnection)
Connector.open(serverUrl,Connector.READ_WRITE, true);
httpConn.setRequestMethod(HttpConnection.GET);
inStream = httpConn.openInputStream();
int read;
while ((read = inStream.read()) != -1) {
sb.append((char) read);
}
return sb.toString();
}
public String getServerReply() {
//serverReply is a class variable.
return serverReply;
}
public void run(){
//call the send method that connects to the server.
serverResponse = sendData(Url);
}
} //end of connector class.
// this class is where all my Command Actions are
//implemented.
public class CommandActionController implements
CommandListener, DataReceiver {
public void commandAction(Command cmd, Displayable d) {
//networkMgr => is the worker class that makes
//connection to the server.
networkMgr = new NetworkConnector("http://localhost
/JsonPhp/login.php?uname=" + loginUserInfo.userName +
"&passwd=" + loginUserInfo.password);
//here am getting the response from the server.
String serverResponse = networkMgr.getServerReply();
//at this point the ServerReponse String is Empty =>
//yet the server is supposed to return some String.
System.out.println("xxxxxxxxxxxxxxxxxx
ServerResponse =" + serverResponse);
}
}//end of CommandListener class.
Your expectations about serverResponse value are wrong; it can be empty at the moment when you attempt to obtain it in commandAction with the code snippet in the question.
In order to get non-empty value, you need to redesign method NetworkConnector.getServerReply() to make it properly wait until thread finishes and server response is indeed obtained.
If you do that, however, you will also have to redesign CommandActionController to keep user interface responsive - your testing with "waiting for the thread that connects to the server" has shown just that.
Redesigned code should just launch the server connect thread and exit the commandAction as soon as possible (possibly changing to some "wait screen" to let user see what happens). Next screen update should be triggered only after server response is obtained.
Consider studying a tutorial specifically targeted on explaining how to properly design this kind applications - Networking, User Experience, and Threads:
This article explains how your MIDlet can make network connections without compromising your user interface. It includes six iterative examples that illustrate multithreaded networking and the use of a wait screen...
Here is how I'd do without java.util.concurrent:
Result handleRequest(){
final String url = // get url
Work work = new Work(url):
Thread t = new Thread(work);
t.start();
// do other stuff
if(t.isAlive()){
// still running
}
// this waits until the work is done
// and it will be safe to access work.result after
// this call has returned.
t.join();
return work.result;
}
and then
class Work implements Runnable{
final String url;
Result result;
public void run(){
this.result = // do your network stuff
}
}
You shouldn't start a thread in the constructor. Also, runnable are meant to be passed to threads. The easiest (and the "proper") way of doing this would be as follows:
Implement a Callable instead of a Runnable.
Use a ExecutorService instead of a Thread
Use Future object to do the processing asynchronously/be responsive to user
Here is a simple example.
class Stuff {
final ExecutorService exec =
Executors.newCachedExecutorService(// please see doc);
Result process(String url){
Future<Result> future = exec.submit(new Work(url));
// do some other stuff
if(future.isDone()){
// return result?
}
return future.get(); // this call will wait until result is available
}
}
and then
class Work implements Callable<Result> {
final String url;
Result call() throws Exception {
// do your network stuff here
return result;
}
}
See documentation of java.util.concurrent.ExecutorService.submit(), java.util.concurrent.Future and java.util.concurrent.Callable for details.

JDBC auto commit for connection shared across threads

I have a servlet where I get a Connection object which is then handed to two worker threads for various activities. I now need to add a transaction on one thread.
If I start a transaction like this:
connection.setAutoCommit(false);
would that impact both threads? I think it would.
Do I have to get a separate connection of each thread?
Thanks
I think what you are doing is very bad practice. You can't share a JDBC connection among threads.
If you are running under an application server (like TOMCAT/JBoss/WebSphere/WebLogic) use a proper DataSource to get your connections as you need them.
Look at your Application Server documentation to get information on how to do that.
You will have something like this in your servlet:
public void doGet(HttpServletRequest req, HttpServletResponse resp)
{
Connection c = null;
try {
c = ...; /* preferred way of getting a connection in your AppServer
// do what you need with your JDBC connection
} catch (Exception e) {
// handle errors
} finally {
c.close(); /* you will need another TRY/CATCH here */
}
}
Similarly, your worker threads will have something like:
public void run()
{
Connection c = null;
try {
c = ...; /* preferred way of getting a connection in your AppServer
// do what you need with your JDBC connection
} catch (Exception e) {
// handle errors
} finally {
c.close(); /* you will need another TRY/CATCH here */
}
}
Eventually, you could set auto commit to whatever you need on separate connection objects.

Opening multiple sessions simultaneously in NHibernate

I finally figured out what's wrong with my code, but I'm not sure how to fix it. I have some background processes running on a separate thread that perform some database maintenance tasks. Here's an exmple of what's happening:
//Both processes share the same instance of ISessionFactory
//but open separate ISessions
//This is running on it's own thread
public void ShortRunningTask()
{
using(var session = _sessionFactory.OpenSession())
{
//Do something quickly here
session.Update(myrecord);
}
}
//This is running on another thread
public void LongRunningTask()
{
using(var session = _sessionFactory.OpenSession())
{
//Do something long here
}
}
Let's say I start LongRunningTask first. While it's running I start ShortRunningTask on another thread. ShortRunningTask finishes up and closes its session. Once LongRunningTask finishes it tries to do something with it's session it created but an error get's thrown saying that the session has already been closed.
Clearly what's happening is that ISessionFactory.OpenSession() is not honoring the fact that I've opened 2 separate sessions. Closing the session opened in ShortRunningTask also closes the session in LongRunningTask How can I fix this? Please help!
Thanks!
UPDATE
So apparently everyone thinks my fix is totally wrong. So here's the configuration I am using:
_sessionFactory = Fluently.Configure()
.Database(
FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2008
.ConnectionString(db => db.Is(
WikipediaMaze.Core.Properties.Settings.Default.WikipediaMazeConnection)))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<IRepository>())
.BuildSessionFactory();
I have no configuration taking place in an xml file. Should there be? What am I missing. Here's another example of how opening multiple sessions fails:
public void OpenMultipleSessionsTest()
{
using(var session1 = _sessionFactory.OpenSession())
{
var user = session1.Get<Users>().ById(1);
user.Name = "New Name";
using(var session2 = _sessionFactory.OpenSession())
{
//Do some other operation here.
}
session1.Update(user);
session1.Flush(); // Throws error 'ISession already closed!'
}
}
I figured out how to fix the problem. I setup my SessionFactory as a singleton at made it [ThreadStatic] like this:
[ThreadStatic]
private ISessionFactory _sessionFactory;
[ThreadStatic]
private bool _isInitialized;
public ISessionFactory SessionFactory
{
get
{
if(!_isInitialized)
{
//Initialize the session factory here
}
}
}
The crux of the problem is that creating sessions on separate threads from the same ISessionFactory is problematic. ISessionFactory does not like multiple ISessions being opened at the same time. Closing one, automatically closes any others that are open. Using the [ThreadStatic] attribute creates a separate ISessionFactory for each thread. This allows me to open and close ISessions on each thread without affecting the others.

Resources