Unity Crash. What causes QObject: Cannot create children for a parent that is in a different thread? - rest

Specs: Unity 2021.3.16/17, MacOS, Android/iOS. I use the rest client plugin with RSG IPromise. Often unity crashes when executing debug.log in the promise resolved callback.
public abstract class ProcedureStep<T> : AbstractProcedureStep, IProcedureStep<T>
{
IPromise<T> IProcedureStep<T>.Run(T context)
{
return new Promise<T>((resolve, reject) =>
{
Run(context).Then(result =>
{
try
{
OnResolve();
resolve(result);
}
catch (Exception e)
{
OnReject(e);
reject(e);
}
}).Catch(e =>
{
OnReject(e);
reject(e);
});
});
}
protected abstract IPromise<T> Run(T context);
protected virtual void OnResolve()
{
//unity crash!!!
//"QObject: Cannot create children for a parent that is in a different thread"
Debug.Log("success");
}
protected virtual void OnReject(Exception e)
{
Debug.LogError(e);
}
}
I found this post forum.gt.iobut i couldn't apply it for my case.

Related

The configured execution strategy 'RetryTransactionExecutionStrategy' does not support user initiated transactions

We wrote our own simple execution strategy to retry saving any data using our DbContext when it runs into a table lock timeout.
public class RetryTransactionExecutionStrategy : DbExecutionStrategy
{
public RetryTransactionExecutionStrategy() : base()
{
}
protected override bool ShouldRetryOn(Exception exception)
{
while (exception != null)
{
if (exception is MySqlException ex
&& ex.Number == 1205) // Deadlock error code
{
return true;
}
exception = exception.InnerException;
}
return false;
}
}
We register it by using the DbConfig class, in the same folder as the context class.
public class DbConfig : DbConfiguration
{
public DbConfig()
{
SetExecutionStrategy(MySqlProviderInvariantName.ProviderName, () => new RetryTransactionExecutionStrategy());
}
}
Now most regular usage of the context will use the retry execution strategy. However, transactions are a more special case. Microsoft mentions usage of them in their documentation, and tells the user to manually call the execution strategy, like this:
var executionStrategy = new RetryTransactionExecutionStrategy();
executionStrategy.Execute(() =>
{
using (PigDbAccountEntities pigDbAccountEntities = new PigDbAccountEntities())
{
using (var dbtransaction = pigDbAccountEntities.Database.BeginTransaction())
{
try
{
//work on some data
pigDbAccountEntities.SaveChanges();
//work on some more data
pigDbAccountEntities.SaveChanges();
//work on even more data
pigDbAccountEntities.SaveChanges();
dbtransaction.Commit();
isSaved = true;
}
catch (Exception ex)
{
dbtransaction.Rollback();
Logger.Instance.Log(LogLevel.ERROR, LogSource.DB, "error in AccountEntityManager.SaveApplicationUser", ex);
}
}
}
});
And yet we still get this error message:
The configured execution strategy 'RetryTransactionExecutionStrategy' does not support user initiated transactions. See http://go.microsoft.com/fwlink/?LinkId=309381 for additional information.
Any idea on what to do/check?

How to catch exception in a callback function in Dart (Flutter)?

I'm using WebSocket variable in my MyWebSocket class. For listen i give a callback function as parameter.
If this callback function throws an exception in calling class MyChat, then i can not catch that exception anywhere.
My simplified code is:
class MyWebSocket {
WebSocket _ws;
...
// initialized in controller: _ws = WebSocket.connect(_some_url_);
// everything works (connect, listen)
...
void listen({void Function(dynamic) myOnListen}) {
try {
_ws.listen(myOnListen)
.onError((e) => print("MyWebSocket in MyChat.onError: $e"));
} catch (e) {
print("Catched in MyWebSocket: $e");
}
}
}
class MyChat {
MyWebSocket _chatWs = MyWebSocket();
...
void initWS() {
try {
_chatWs.listen(myOnListen: processMsg);
} catch (e) {
print("Catched in MyChat: $e");
}
}
void processMsg(dynamic msg) {
if(_some_stuff_like_invalid_msg_or_not_logged_in_...)
throw Exception("There is my Exception");
}
}
I have built try-catch in every possible place to catch exceptions - no success, i got only unhandled exception:
E/flutter: [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: Exception: There is my Exception
E/flutter: #0 MyChat.processMsg
Beware that you cannot use the passed listener as a key for later removal. For that you can pass the new listener created in MyWebSocket class when listen() is called, then use this key to remove the listener.
class MyWebSocket {
WebSocket _ws;
void listen({void Function(dynamic) myOnListen, void Function(Error) onError}) {
try {
_ws.listen((){
try {
myOnListen({"label": "DATA"});
} catch (e) {
if(onError is Function)
onError(e)
}
})
.onError(onError);
} catch (e) {
print("Catched in MyWebSocket: $e");
}
}
}
class MyChat {
MyWebSocket _chatWs = MyWebSocket();
void initWS() {
try {
_chatWs.listen(myOnListen: processMsg, onError: (Error error){
print("ERROR: "+error.toString());
});
} catch (e) {
print("Catched in MyChat: $e");
}
}
void processMsg(dynamic msg) {
if(_some_stuff_like_invalid_msg_or_not_logged_in_...)
throw Exception("There is my Exception");
}
}
You need to handle it inside your processMsg
If you analyze carefully the execution of your code the _ws.listent register a listener for when you receive a message and that will happen in the FUTURE, but you don't get an error WHILE you are REGISTERING your listener that's why that doesn't work the way you expect.
processMsg will do something in the future, it will throw an error and it's at the end of the pipeline.
You are simulating an exception and nothing is handling it, it happens in a different stack frame, in the future.
The void listen({void Function(dynamic) myOnListen}) function execution is long gone when you receive and you precessMsg.
Alternatively you could do:
Function tryCatchHOF(Function cb) {
decorated(dynamic param) {
try {
cb(param);
} catch (e) {
print("$e");
}
}
;
return decorated;
}
void processMsg(dynamic msg) {
if (true) throw Exception("There is my Exception");
}
var processMsgWithTryCatch = tryCatchHOF(processMsg);
processMsgWithTryCatch('');
and then pass processMsgWithTryCatch down to your listener if you don't want to handle inside processMsg
I hope that make sense

How to detect every mouse event in system using java

How to detect every mouse event in system using java?
I have tried using Point class to catch mouse motion but that thing was not so convenient.
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.keyboard.NativeKeyEvent;
import org.jnativehook.keyboard.NativeKeyListener;
class GlobalKeyListenerExample implements NativeKeyListener {
public void nativeKeyPressed(NativeKeyEvent e) {
System.out.println("Key Pressed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
if (e.getKeyCode() == NativeKeyEvent.VK_ESCAPE) {
}
}
public void nativeKeyReleased(NativeKeyEvent e) {
System.out.println("Key Released: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
}
public void nativeKeyTyped(NativeKeyEvent e) {
System.out.println("Key Typed: " + e.getKeyText(e.getKeyCode()));
}
public GlobalKeyListenerExample()
{
try {
GlobalScreen.registerNativeHook();
}
catch (NativeHookException ex) {
System.err.println("There was a problem registering the native hook.");
System.err.println(ex.getMessage());
System.exit(1);
}
GlobalScreen.getInstance().addNativeKeyListener(this);
}
public static void main(String[] args) {
try {
GlobalScreen.registerNativeHook();
}
catch (NativeHookException ex) {
System.err.println("There was a problem registering the native hook.");
System.err.println(ex.getMessage());
System.exit(1);
}
//Construct the example object and initialze native hook.
GlobalScreen.getInstance().addNativeKeyListener(new GlobalKeyListenerExample());
}
}

Show previous instance of RCP application

I had an rcp application which runs for only first run, when a user attempts to re-execute the application, second instance behaves as a client which encodes and sends its arguments over the socket to the first instance which acts as a server and then exits silently. The first instance receives and decodes that message, then behaves as if it had been invoked with those arguments.
so far so good i made internal protocol specification for passing arguments between two instances.
I could not bring the first instance(RCP application) to front. It is in minimized state only,
this is in continuation to my previous question
the change i made to previous post is start method of application class
public Object start(IApplicationContext context) throws Exception {
if (!ApplicationInstanceManager.registerInstance()) {
return IApplication.EXIT_OK;
}
ApplicationInstanceManager
.setApplicationInstanceListener(new ApplicationInstanceListener() {
public void newInstanceCreated() {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
System.out.println("New instance detected...");
//Display.getCurrent().getActiveShell()
.forceActive();// this gives null
// pointer exception
// hence commented
}
});
}
});
Display display = PlatformUI.createDisplay();
try {
int returnCode = PlatformUI.createAndRunWorkbench(display,
new ApplicationWorkbenchAdvisor());
if (returnCode == PlatformUI.RETURN_RESTART)
return IApplication.EXIT_RESTART;
else
return IApplication.EXIT_OK;
} finally {
display.dispose();
}
}
below line is stopping me to bring Application to front
Display.getCurrent().getActiveShell().forceActive();
generates null pointer exception at getActiveShell()
how can i maximize the previous instance or bring it to front
I wrote an instance manager to restrict my RCP to a single instance.
Here's the code that goes in Application.java, in the start method:
if (!ApplicationInstanceManager.registerInstance()) {
return IApplication.EXIT_OK;
}
ApplicationInstanceManager
.setApplicationInstanceListener(new ApplicationInstanceListener() {
public void newInstanceCreated() {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
if (DEBUG)
System.out.println("New instance detected...");
Display.getCurrent().getActiveShell().forceActive();
}
});
}
});
Here's the listener interface:
public interface ApplicationInstanceListener {
public void newInstanceCreated();
}
And here's the Manager class:
public class ApplicationInstanceManager {
private static final boolean DEBUG = true;
private static ApplicationInstanceListener subListener;
/** Randomly chosen, but static, high socket number */
public static final int SINGLE_INSTANCE_NETWORK_SOCKET = 44331;
/** Must end with newline */
public static final String SINGLE_INSTANCE_SHARED_KEY = "$$RabidNewInstance$$\n";
/**
* Registers this instance of the application.
*
* #return true if first instance, false if not.
*/
public static boolean registerInstance() {
// returnValueOnError should be true if lenient (allows app to run on
// network error) or false if strict.
boolean returnValueOnError = true;
// try to open network socket
// if success, listen to socket for new instance message, return true
// if unable to open, connect to existing and send new instance message,
// return false
try {
final ServerSocket socket = new ServerSocket(
SINGLE_INSTANCE_NETWORK_SOCKET, 10, InetAddress
.getLocalHost());
if (DEBUG)
System.out
.println("Listening for application instances on socket "
+ SINGLE_INSTANCE_NETWORK_SOCKET);
Thread instanceListenerThread = new InstanceListenerThread(socket);
instanceListenerThread.start();
// listen
} catch (UnknownHostException e) {
EclipseLogging.logError(RabidPlugin.getDefault(),
RabidPlugin.PLUGIN_ID, e);
return returnValueOnError;
} catch (IOException e) {
return portTaken(returnValueOnError, e);
}
return true;
}
private static boolean portTaken(boolean returnValueOnError, IOException e) {
if (DEBUG)
System.out.println("Port is already taken. "
+ "Notifying first instance.");
try {
Socket clientSocket = new Socket(InetAddress.getLocalHost(),
SINGLE_INSTANCE_NETWORK_SOCKET);
OutputStream out = clientSocket.getOutputStream();
out.write(SINGLE_INSTANCE_SHARED_KEY.getBytes());
out.close();
clientSocket.close();
System.out.println("Successfully notified first instance.");
return false;
} catch (UnknownHostException e1) {
EclipseLogging.logError(RabidPlugin.getDefault(),
RabidPlugin.PLUGIN_ID, e);
return returnValueOnError;
} catch (IOException e1) {
EclipseLogging
.logError(
RabidPlugin.getDefault(),
RabidPlugin.PLUGIN_ID,
"Error connecting to local port for single instance notification",
e);
return returnValueOnError;
}
}
public static void setApplicationInstanceListener(
ApplicationInstanceListener listener) {
subListener = listener;
}
private static void fireNewInstance() {
if (subListener != null) {
subListener.newInstanceCreated();
}
}
public static void main(String[] args) {
if (!ApplicationInstanceManager.registerInstance()) {
// instance already running.
System.out.println("Another instance of this application "
+ "is already running. Exiting.");
System.exit(0);
}
ApplicationInstanceManager
.setApplicationInstanceListener(new ApplicationInstanceListener() {
public void newInstanceCreated() {
System.out.println("New instance detected...");
// this is where your handler code goes...
}
});
}
public static class InstanceListenerThread extends Thread {
private ServerSocket socket;
public InstanceListenerThread(ServerSocket socket) {
this.socket = socket;
}
#Override
public void run() {
boolean socketClosed = false;
while (!socketClosed) {
if (socket.isClosed()) {
socketClosed = true;
} else {
try {
Socket client = socket.accept();
BufferedReader in = new BufferedReader(
new InputStreamReader(client.getInputStream()));
String message = in.readLine();
if (SINGLE_INSTANCE_SHARED_KEY.trim().equals(
message.trim())) {
if (DEBUG)
System.out.println("Shared key matched - "
+ "new application instance found");
fireNewInstance();
}
in.close();
client.close();
} catch (IOException e) {
socketClosed = true;
}
}
}
}
}
}
After your IApplication start up, you can also check and lock the OSGi instance location using org.eclipse.osgi.service.datalocation.Location.isSet() and org.eclipse.osgi.service.datalocation.Location.lock()
The location is usually retrieved from your Activator using code like:
public Location getInstanceLocation() {
if (locationTracker == null) {
Filter filter = null;
try {
filter = context.createFilter(Location.INSTANCE_FILTER);
} catch (InvalidSyntaxException e) {
// ignore this. It should never happen as we have tested the
// above format.
}
locationTracker = new ServiceTracker(context, filter, null);
locationTracker.open();
}
return (Location) locationTracker.getService();
}

GWT client "throws Exception" cause compling problem

I try to use get result from a api called j-calais, and then out put the result on a web page, i write all the code in client, but it cant compile right, dont know why??? please help. the source code like below:
there is no obvious error arise, but it cant be compile successfully..... thanks a lot:
public void onModuleLoad() {
// Create table for stock data.
stocksFlexTable.setText(0, 0, "Type");
stocksFlexTable.setText(0, 1, "Name");
// Assemble Add Stock panel.
addPanel.add(newSymbolTextBox);
addPanel.add(addStockButton);
// Assemble Main panel.
mainPanel.add(stocksFlexTable);
mainPanel.add(addPanel);
mainPanel.add(lastUpdatedLabel);
// Associate the Main panel with the HTML host page.
RootPanel.get("stockList").add(mainPanel);
// Move cursor focus to the input box.
newSymbolTextBox.setFocus(true);
// Listen for mouse events on the Add button.
addStockButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
try {
addStock();
} catch (Exception e) {
e.printStackTrace();
}
}
});
// Listen for keyboard events in the input box.
newSymbolTextBox.addKeyPressHandler(new KeyPressHandler() {
public void onKeyPress(KeyPressEvent event) {
if (event.getCharCode() == KeyCodes.KEY_ENTER) {
try {
addStock();
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
}
private void addStock() throws Exception {
final String url_s = newSymbolTextBox.getText().toUpperCase().trim();
newSymbolTextBox.setFocus(true);
newSymbolTextBox.setText("");
int row = stocksFlexTable.getRowCount();
CalaisClient client = new CalaisRestClient("ysw5rx69jkvdnzqf6sgjduqj");
System.out.print("read success...\n");
URL url = new URL(url_s);
CalaisResponse response = client.analyze(url);
for (CalaisObject entity : response.getEntities()) {
System.out.println(entity.getField("_type") + ":"
+ entity.getField("name"));
stocks.add(entity.getField("_type"));
stocksFlexTable.setText(row, 0, entity.getField("_type"));
stocksFlexTable.setText(row, 1, entity.getField("name"));
}
for (CalaisObject topic : response.getTopics()) {
System.out.println(topic.getField("categoryName"));
}
}
}
GWT only handles unchecked exceptions so you can throw Runtime Exceptions
or write your own Exception that extends from Runtime Exception then it will not cause any compile time problem
void f() throws NullPointerException // will not cause any problem because it is Runtime exception so unchecked
void f() throws IllegalAccessException // it is checked exception so there will be problem at compile time