TesseractApi Xamarin Infinite Freeze - xamarin.forms

I am using Tessaract's Xamarin Forms Nuget(https://github.com/halkar/Tesseract.Xamarin), and am trying to scan a picture taken by the Android Device. This is the code that I am using:
private async System.Threading.Tasks.Task<string> OCRAsync(byte[] bytes)
{
TesseractApi api;
api = new TesseractApi(this, AssetsDeployment.OncePerInitialization);
await api.Init("bul");
await api.SetImage(bytes);
var detectedText = api.Results(PageIteratorLevel.Block);
result = string.Empty;
if (detectedText != null)
{
foreach (var annotation in detectedText)
{
result = FindWordInDictionary(annotation.Text);
}
}
return result;
}
The method is called from a synchronized method like this:
var task = OCRAsync(data);
result = task.Result;
Whenever the compiler gets to "await api.Init("bul");" the app freezes indefinitely. Do you know what may cause this problem? Thank you.

The problem was that I needed to give a file location in the .init function:
await api.Init(pathToDataFile, "bul");

Related

send notification from background worker

am using ABP to build my project
I have a module to generate big size files using background worker, and after each successful file generated I need to send notification, but is not working !
I've put the background job in the core project and the queue in the engine project,
the DB notification tables are updated successfully (new record inserted so the pull notification will work fine !), but the browser doesn't receive the notification (so I can inform him that his file is ready), but there is no errors and no any notification send to the browser.
here is the worker class:
public class GeneratedFileWorker : BackgroundWorkerBase, ISingletonDependency
{
.
.
.
[UnitOfWork]
[AutomaticRetry(Attempts = 0)]
public override async System.Threading.Tasks.Task ExecuteAsync()
{
var notificationData = new NotificationData();
notificationData["URL"] = "app/main/data/generatedfiles";
using (AbpSession.Use(TenantConsts.DefaultTenantId, TenantConsts.UserServiceId))
{
GetDownloadArticleInput getDownloadArticleInput = new GetDownloadArticleInput();
if (pendingRequest is not null)
{
var entityType = _lookupItemManager.Get(pendingRequest.EntityTypeId).Code;
dynamic Args = JsonConvert.DeserializeObject<GetDownloadArticleInput>(String.Empty);
switch (entityType)
{
case "Article":
Args = JsonConvert.DeserializeObject<GetDownloadArticleInput>(pendingRequest.ExtensionData);
break;
case "ArticlesList":
Args = JsonConvert.DeserializeObject<GetDownloadArticlesInput>(pendingRequest.ExtensionData);
break;
};
GeneratedFile generatedFileDto = new GeneratedFile();
try
{
generatedFileDto = await _generateFile.Generate(Args);
await _appNotifier.SendMessageAsync(new UserIdentifier(1, pendingRequest.CreatorUserId.Value),string.Format(_LocalizationSource.GetString("GeneratedFile.fileIsNotready"), _lookupItemManager.GetTitle(pendingRequest.EntityTypeId)), notificationData, NotificationSeverity.Error);
else
await _appNotifier.SendMessageAsync(new UserIdentifier(1, pendingRequest.CreatorUserId.Value), string.Format(_LocalizationSource.GetString("GeneratedFile.fileIsready"), _lookupItemManager.GetTitle(pendingRequest.EntityTypeId)), notificationData, NotificationSeverity.Success);
}
catch (Exception ex)
{
pendingRequest.CurrentStateId = _lookupItemManager.GetByCode(LookupCategories.GeneratedFileStatus, "Failed").Id;
pendingRequest.OperationResult = ex.ToString();
await _generatedFileRepository.UpdateAsync(pendingRequest);
await _appNotifier.SendMessageAsync(new UserIdentifier(1, pendingRequest.CreatorUserId.Value), string.Format(_LocalizationSource.GetString("GeneratedFile.fileIsNotready"), _lookupItemManager.GetTitle(pendingRequest.EntityTypeId)), notificationData, NotificationSeverity.Error);
}
}
}
}
I have 2 cases here:
first one working when I define the queue in the host project, and
second one not working when I define the queue in the engine project

Blazor WebAssembly **Microsoft.JSInterop.JSException** Error: The value 'sessionStorage.length' is not a function

From a basic standpoint what I am trying to do is get a list of keys (key names) from session storage.
The way I am trying to do this is by calling the JsRuntime.InvokeAsync method to:
Get the number of keys in session storage, and
loop thought the number of items in session storage and get the key name.
public async Task<List<string>> GetKeysAsync()
{
var dataToReturn = new List<string>();
var storageLength = await JsRuntime.InvokeAsync<string>("sessionStorage.length");
if (int.TryParse(storageLength, out var slength))
{
for (var i = 1; i <= slength; i++)
{
dataToReturn.Add(await JsRuntime.InvokeAsync<string>($"sessionStorage.key({i})"));
}
}
return dataToReturn;
}
When calling the JsRuntime.InvokeAsync($"sessionStorage.length")) or JsRuntime.InvokeAsync($"sessionStorage.key(0)")) I am getting an error "The value 'sessionStorage.length' is not a function." or The value 'sessionStorage.key(0)' is not a function.
I am able to get a single items using the key name from session storage without issue like in the following example.
public async Task<string> GetStringAsync(string key)
{
return await JsRuntime.InvokeAsync<string>("sessionStorage.getItem", key);
}
When I use the .length or .key(0) in the Chrome console they work as expected, but not when using the JsRuntime.
I was able to get this to work without using the sessionStorage.length property. I am not 100% happy with the solution, but it does work as needed.
Please see below code. The main thing on the .key was to use the count as a separate variable in the InvokeAsync method.
I think the reason for this is the JsRuntime.InvokeAsync method adds the () automatically to the end of the request, so sessionStorage.length is becoming sessionStorage.length() thus will not work. sessionStorage.key(0) was becoming sessionStorage.key(0)(). etc. Just that is just a guess.
public async Task<List<string>> GetKeysAsync()
{
var dataToReturn = new List<string>();
var dataPoint = "1";
while (!string.IsNullOrEmpty(dataPoint) )
{
dataPoint = await JsRuntime.InvokeAsync<string>($"sessionStorage.key", $"{dataToReturn.Count}");
if (!string.IsNullOrEmpty(dataPoint))
dataToReturn.Add(dataPoint);
}
return dataToReturn;
}

How to fix the 'FileSystemException: An async operation is currently pending'?

I wrote a torrent download demo , look like this:
var peers....
for(var i =0;i < length;i++){
var peer = peers[i];
peer.start((List<int> data){
_downloadFile.write(begin,end,data);
});
}
I mean that there are mutiple peer try to access the _file.
`_downloadFile` code looks like this:
....
var _access = _file.open(mode:FileMode.writeOnlyAppend);
...
Future write(int begin,int end, List<int> block) async{
....
await _access.setPosition(begin);
await _access.writeFrom(block);
....
}
And it will throw exception : FileSystemException: An async operation is currently pending
I think the reason is that different fork invoke setPosition, so I try to make each fork to wait the write operation over:
`_downloadFile` code look like this:
....
var _access = _file.open(mode:FileMode.writeOnlyAppend);
var _lock;
...
Future write(int begin,int end, List<int> block) async{
if(_lock != null) await _lock;
var c = Completer();
_lock = c.future;
....
await _access.setPosition(begin);
await _access.writeFrom(block);
c.complete();
....
}
If I understand correctly, when peer recieves data , it will call write method , then it should wait the _lock completed, but I still get FileSystemException.
Now I have to use Stream , with its pause and resume method to avoid this exception.
Can someone tell me what's the problems with the last codes? why the _lock does not work? Does Dart have something like 'object lock'?
Thanks very much!

Unity3d with Firebase: Can't Start Coroutine

Greeting,
I'm currently facing a problem that my coroutine can't start. This is the first time I facing this issues and I can't find a proper solution online. Much appreciated if anyone can point me to the right direction to solve this issue.
Here are the code.
path_reference.GetDownloadUrlAsync().ContinueWith((Task<Uri> task) => {
if (!task.IsFaulted && !task.IsCanceled)
{
Debug.Log("Download URL: " + task.Result);
StartCoroutine(DownloadStuff(task.Result));
}
else
{
Debug.Log(task.Exception.ToString());
}
});
}
IEnumerator DownloadStuff(Uri uri)
{
Debug.Log("Start Download");
using (var www = UnityWebRequestTexture.GetTexture(uri))
{
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
{
Debug.Log(www.error);
}
else
{
var texture = DownloadHandlerTexture.GetContent(www);
//Texture2D texture = new Texture2D(1, 1);
//if you need sprite for SpriteRenderer or Image
Sprite sprite = Sprite.Create(texture, new Rect(0.0f, 0.0f, texture.width,
texture.height), new Vector2(0.5f, 0.5f), 100.0f);
Debug.Log("Finished downloading!");
}
Debug.Log(www.downloadProgress);
}
}'
The task returned by Firebase probably finishes execution on a thread other than the main thread, and Unity coroutines can only run on the main thread.
Unity's support of multithreading and async is pretty spotty, including "eating" some errors if the continuations of those errors would execute on another thread other than the main thread.
To fix this, you need to change the function that starts your coroutine:
try {
// Important: ConfigureAwait(true) ensures the code after this will run in the
// same thread as the code before (which is the main thread!)
var url = await path_reference.GetDownloadUrlAsync().ConfigureAwait(true);
StartCoroutine(DownloadStuff(url));
} catch (Exception ex) {
// Tip: when logging errors, use LogException and pass the whole exception,
// that way you will get pretty links to the error line in the whole stack trace.
Debug.LogException(ex);
}
As an aside, I usually have a few extension methods on all my projects to deal with that while staying in async-world instead of coroutine-world (because at least with async I can catch errors and not just "halt and catch fire" like Unity's coroutines)
The main ones are:
public static Task ToTask(this YieldInstruction self, MonoBehaviour owner) {
var source = new TaskCompletionSource<object>();
IEnumerable Routine() {
yield return self;
source.SetResult(null);
}
return source.Task;
}
private static Task SendAsync(this UnityWebRequest self, MonoBehaviour owner) {
var source = new TaskCompletionSource<object>();
await self.SendWebRequest().ToTask(owner);
if (
self.isHttpError
|| self.isNetworkError
) {
source.SetException(new Exception(request.error));
yield break;
}
source.SetResult(null);
}
Which you can use like this, inside a MonoBehaviour:
await new WaitForSeconds(0.2f).ToTask(this);
UnityWebRequest request = /* etc */;
await request.SendAsync(this);
var texture = DownloadHandlerTexture.GetContent(request);
Note that these methods do not require ConfigureAwait, since their SetResult/SetException invocations are ran from Unity-provided coroutine continuations.

Obscure Unity Firebase Realtime Database Error: "Custom Run loops are not supported"?

I am currently attemping to build a custom Editor tool for Unity that utilizes the Firebase Realtime Database. This tool would allow someone to right-click on a scene asset in the inspector and select to 'lock' or 'unlock' the scene. Within our Firebase Database, this locking is represented by a dictionary, with each scene name as a key and each value being either "locked" or "unlocked". This funcitonality will be expanded later, but for now, I'm just trying to get things set up so that I can actually connect to and use the Firebase Realtime Database.
I had looked at the Firebase Quickstart Unity project for the Realtime Database (the one that functions like a leaderboard) and saw that it worked fine. I could replace the database URL in the project with the URL for my app's database, and when I entered in values, they appeared inside my realtime database.
So, I based the code for my custom editor script on the code from the quickstart. In fact, I copy-pasted most of it. I will post the script itself, and then describe the errors I receive, as well as the lines that give the errors:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using Firebase;
using Firebase.Unity.Editor;
using Firebase.Database;
[CustomEditor(typeof(SceneAsset))]
[ExecuteInEditMode]
public class SceneLockingEditor : Editor
{
static string sceneName;
DependencyStatus dependencyStatus = DependencyStatus.UnavailableOther;
protected virtual void OnEnable()
{
Debug.Log("OnEnable Called");
sceneName = target.name;
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task => {
dependencyStatus = task.Result;
if (dependencyStatus == DependencyStatus.Available)
{
InitializeFirebase();
}
else
{
Debug.LogError(
"Could not resolve all Firebase dependencies: " + dependencyStatus);
}
});
}
// Initialize the Firebase database:
protected virtual void InitializeFirebase()
{
Debug.Log("Initializing Firebase");
FirebaseApp app = FirebaseApp.DefaultInstance;
app.SetEditorDatabaseUrl(CENSORING MY DATABASE SORRY);
if (app.Options.DatabaseUrl != null) app.SetEditorDatabaseUrl(app.Options.DatabaseUrl);
}
static TransactionResult SceneLockTransaction(MutableData mutableData)
{
List<object> sceneLocks = mutableData.Value as List<object>;
if (sceneLocks == null)
{
sceneLocks = new List<object>();
}
if(mutableData.ChildrenCount > 0)
{
//Look at every child in the scene locks directory.
foreach (var child in sceneLocks)
{
Debug.Log("Checking next child.");
if (!(child is Dictionary<string, object>))
continue;
//If we find the scene we're looking for...
Debug.Log("Checking if the scene has the name we want");
foreach(string key in ((Dictionary<string, object>)child).Keys)
{
Debug.Log("Key: " + key);
}
if(((Dictionary<string, object>)child).ContainsKey(sceneName))
{
string childLockStatus = (string)((Dictionary<string, object>)child)["lockStatus"];
//If the scene is already locked, just abort.
if (childLockStatus == "locked")
{
Debug.Log("Scene is already locked. Abort.");
return TransactionResult.Abort();
}
else
{
Debug.Log("Scene existed in the database and was not locked. Locking it.");
// If the scene existed in the database but was not locked, we will lock it.
((Dictionary<string, object>)child)[sceneName] = "locked";
// You must set the Value to indicate data at that location has changed.
mutableData.Value = sceneLocks;
return TransactionResult.Success(mutableData);
}
}
}
}
Debug.Log("Scene did not exist in the database. Adding it as locked.");
// If the scene didn't exist in the database before, we will add it as locked.
Dictionary<string, object> newSceneLock = new Dictionary<string, object>();
newSceneLock[sceneName] = "locked";
sceneLocks.Add(newSceneLock);
// You must set the Value to indicate data at that location has changed.
mutableData.Value = sceneLocks;
return TransactionResult.Success(mutableData);
}
static TransactionResult SceneUnlockTransaction(MutableData mutableData)
{
List<object> sceneLocks = mutableData.Value as List<object>;
if (sceneLocks == null)
{
sceneLocks = new List<object>();
}
if (mutableData.ChildrenCount > 0)
{
//Look at every child in the scene locks directory.
foreach (var child in sceneLocks)
{
Debug.Log("Checking next child.");
if (!(child is Dictionary<string, object>))
continue;
//If we find the scene we're looking for...
Debug.Log("Checking if the scene has the name we want");
foreach (string key in ((Dictionary<string, object>)child).Keys)
{
Debug.Log("Key: " + key);
}
if (((Dictionary<string, object>)child).ContainsKey(sceneName))
{
string childLockStatus = (string)((Dictionary<string, object>)child)["lockStatus"];
//If the scene is already locked, just abort.
if (childLockStatus == "unlocked")
{
Debug.Log("Scene is already unlocked. Abort.");
return TransactionResult.Abort();
}
else
{
Debug.Log("Scene existed in the database and was locked. Unlocking it.");
// If the scene existed in the database but was not locked, we will lock it.
((Dictionary<string, object>)child)[sceneName] = "unlocked";
// You must set the Value to indicate data at that location has changed.
mutableData.Value = sceneLocks;
return TransactionResult.Success(mutableData);
}
}
}
}
Debug.Log("Scene did not exist in the database. Adding it as unlocked.");
// If the scene didn't exist in the database before, we will add it as locked.
Dictionary<string, object> newSceneLock = new Dictionary<string, object>();
newSceneLock[sceneName] = "unlocked";
sceneLocks.Add(newSceneLock);
// You must set the Value to indicate data at that location has changed.
mutableData.Value = sceneLocks;
return TransactionResult.Success(mutableData);
}
static public void AddSceneLock()
{
Debug.Log("Attempting to add scene lock to database.");
DatabaseReference reference = FirebaseDatabase.DefaultInstance.GetReference("SceneLocks");
Debug.Log("Running Transaction...");
// Use a transaction to ensure that we do not encounter issues with
// simultaneous updates that otherwise might create more than MaxScores top scores.
reference.RunTransaction(SceneLockTransaction)
.ContinueWith(task => {
if (task.Exception != null)
{
Debug.Log(task.Exception.ToString());
}
else if (task.IsCompleted)
{
Debug.Log("Transaction complete.");
}
});
}
static public void RemoveSceneLock()
{
Debug.Log("Attempting to add scene lock to database.");
DatabaseReference reference = FirebaseDatabase.DefaultInstance.GetReference("SceneLocks");
Debug.Log("Running Transaction...");
// Use a transaction to ensure that we do not encounter issues with
// simultaneous updates that otherwise might create more than MaxScores top scores.
reference.RunTransaction(SceneUnlockTransaction)
.ContinueWith(task => {
if (task.Exception != null)
{
Debug.Log(task.Exception.ToString());
}
else if (task.IsCompleted)
{
Debug.Log("Transaction complete.");
}
});
}
[MenuItem("CONTEXT/SceneAsset/Lock Scene", false, 0)]
public static void LockScene()
{
Debug.Log("LockScene Called for scene " + sceneName + ".");
AddSceneLock();
}
[MenuItem("CONTEXT/SceneAsset/Unlock Scene", false, 0)]
public static void UnlockScene()
{
Debug.Log("UnlockScene Called for scene " + sceneName + ".");
RemoveSceneLock();
}
}
The errors always come from this line:
FirebaseDatabase.DefaultInstance.GetReference("SceneLocks");
Any line that has to do with "FirebaseDatabase.DefaultInstance" will throw one of the following two errors
Error 1:
InvalidOperationException: SyncContext not initialized.
Firebase.Unity.UnitySynchronizationContext.get_Instance ()
Firebase.Platform.PlatformInformation.get_SynchronizationContext ()
Firebase.FirebaseApp.get_ThreadSynchronizationContext ()
Firebase.Database.DotNet.DotNetPlatform+SynchronizationContextTarget..ctor ()
Firebase.Database.DotNet.DotNetPlatform.NewEventTarget (Firebase.Database.Internal.Core.Context c)
Firebase.Database.Internal.Core.Context.EnsureEventTarget ()
Firebase.Database.Internal.Core.Context.InitServices ()
Firebase.Database.Internal.Core.Context.Freeze ()
Firebase.Database.Internal.Core.RepoManager.CreateLocalRepo (Firebase.Database.Internal.Core.Context ctx, Firebase.Database.Internal.Core.RepoInfo info, Firebase.Database.FirebaseDatabase firebaseDatabase)
Firebase.Database.Internal.Core.RepoManager.CreateRepo (Firebase.Database.Internal.Core.Context ctx, Firebase.Database.Internal.Core.RepoInfo info, Firebase.Database.FirebaseDatabase firebaseDatabase)
Firebase.Database.FirebaseDatabase.EnsureRepo ()
Firebase.Database.FirebaseDatabase.get_RootReference ()
SceneLockingEditor.OnInspectorGUI () (at Assets/Bitloft/SCRIPTS/Editor/SceneLockingEditor.cs:37)
UnityEditor.InspectorWindow.DrawEditor (UnityEditor.Editor[] editors, Int32 editorIndex, Boolean rebuildOptimizedGUIBlock, System.Boolean& showImportedObjectBarNext, UnityEngine.Rect& importedObjectBarRect) (at C:/buildslave/unity/build/Editor/Mono/Inspector/InspectorWindow.cs:1242)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
Error 2:
Exception: Custom Run loops are not supported!
Firebase.Database.Internal.Core.Context.GetExecutorService ()
Firebase.Database.Internal.Core.Context.GetConnectionContext ()
Firebase.Database.Internal.Core.Context.NewPersistentConnection (Firebase.Database.Internal.Connection.HostInfo info, IDelegate delegate_)
Firebase.Database.Internal.Core.Repo..ctor (Firebase.Database.Internal.Core.RepoInfo repoInfo, Firebase.Database.Internal.Core.Context ctx, Firebase.Database.FirebaseDatabase firebaseDatabase)
Firebase.Database.Internal.Core.RepoManager.CreateLocalRepo (Firebase.Database.Internal.Core.Context ctx, Firebase.Database.Internal.Core.RepoInfo info, Firebase.Database.FirebaseDatabase firebaseDatabase)
Firebase.Database.Internal.Core.RepoManager.CreateRepo (Firebase.Database.Internal.Core.Context ctx, Firebase.Database.Internal.Core.RepoInfo info, Firebase.Database.FirebaseDatabase firebaseDatabase)
Firebase.Database.FirebaseDatabase.EnsureRepo ()
Firebase.Database.FirebaseDatabase.get_RootReference ()
SceneLockingEditor.OnInspectorGUI () (at Assets/Bitloft/SCRIPTS/Editor/SceneLockingEditor.cs:37)
UnityEditor.InspectorWindow.DrawEditor (UnityEditor.Editor[] editors, Int32 editorIndex, Boolean rebuildOptimizedGUIBlock, System.Boolean& showImportedObjectBarNext, UnityEngine.Rect& importedObjectBarRect) (at C:/buildslave/unity/build/Editor/Mono/Inspector/InspectorWindow.cs:1242)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
It's always one error or the other, and I can't determine what causes one error to appear rather than the other. Both errors stop whatever operation I'm trying to do on the database, which means I can't interact with my database at all.
I've taken a look at the quickstart projects and watched some videos of people setting up Firebase to work with their projects, and I can't seem to determine what I have messed up during the process. I have imported my google-services.json into the unity project. The quickstart projects worked just fine interacting with my database. It's just this particular script that won't work. I cannot find any mention of these two errors anywhere on Google. I even contacted the official Firebase support and they couldn't give me any advice on what the errors mean or what could be causing them.
I considered one problem might be in my initialization function. Instead of doing:
FirebaseApp app = FirebaseApp.DefaultInstance;
I figured that maybe I am supposed to use FirebaseApp.Create() with a custom name passed in, but that resulted in the same errors being thrown on the same line. I am at a loss for how to proceed with this problem. I don't know of anyone else who has had these particular errors, and I've done very much experimentation with different ways to access the database over the past several days. If anybody has an idea of what I am doing wrong here, or what causes these errors (and, how to fix them), I would really appreciate it.
At first you should initialize firebase with new instance of FirebaseApp with unique name. I do it like this:
FirebaseApp firebaseApp = FirebaseApp.Create(
FirebaseApp.DefaultInstance.Options,
"FIREBASE_EDITOR");
The second is setup references (DatabaseReference, StorageReference etc.) with this firebaseApp instance and use it only after FirebaseApp.CheckAndFixDependenciesAsync()
Overall code will look like this:
public static void Initialize(bool isEditor = false)
{
if (isEditor)
{
FirebaseApp firebaseApp = FirebaseApp.Create(
FirebaseApp.DefaultInstance.Options,
"FIREBASE_EDITOR");
firebaseApp.SetEditorDatabaseUrl("https://project.firebaseio.com/");
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
{
if (task.Result == DependencyStatus.Available)
{
database = FirebaseDatabase.GetInstance(firebaseApp).RootReference;
storage = FirebaseStorage.GetInstance(firebaseApp).RootReference;
auth = FirebaseAuth.GetAuth(firebaseApp);
}
else
{
Debug.LogError(
"Could not resolve all Firebase dependencies: " + task.Result);
}
});
}
else
{
FirebaseApp.DefaultInstance.SetEditorDatabaseUrl("https://project.firebaseio.com/");
database = FirebaseDatabase.DefaultInstance.RootReference;
storage = FirebaseStorage.DefaultInstance.RootReference;
auth = FirebaseAuth.DefaultInstance;
}
IsInitialized = true;
}
I had the same errors. I spent several hours solving this and it worked for me

Resources