Uno Platform camera preview control - uno-platform

How can I add an camera preview in a uno XAML Page?
Could be like this example
https://learn.microsoft.com/en-us/windows/uwp/audio-video-camera/simple-camera-preview-access
But the CameraCapture.InitializeAsyn is not implemented on Uno.
When it runs the following exception is thrown:
System.NotImplementedException: The member IAsyncAction
MediaCapture.InitializeAsync() is not implemented in Uno.
If is possible to use native android code, this sample do what I need.
https://learn.microsoft.com/en-us/samples/xamarin/monodroid-samples/android50-camera2basic/
Thanks!

On Android, you have at least two ways for doing something similar:
You can use the following, with native android intents, that you'll need to make conditional with __ANDROID__:
public MainPage()
{
...
BaseActivity.Current.ActivityResult += Current_ActivityResult;
}
private void Current_ActivityResult(object sender, BaseActivity.ActivityResultEventArgs e)
{
if (e.Data != null)
{
var bitmap = (Bitmap)e.Data.Extras.Get("data");
image.Source = bitmap;
}
else
{
image.Source = null;
}
}
public void button_Click(object sender, RoutedEventArgs e)
{
var intent = new Intent(MediaStore.ActionImageCapture);
BaseActivity.Current.StartActivityForResult(intent, 0);
}
or using the CameraCaptureUI class:
{
try
{
var captureUI = new CameraCaptureUI();
captureUI.PhotoSettings.Format = CameraCaptureUIPhotoFormat.Jpeg;
captureUI.PhotoSettings.CroppedSizeInPixels = new Size(200, 200);
var photo = await captureUI.CaptureFileAsync(CameraCaptureUIMode.Photo);
if (photo == null)
{
return;
}
else
{
var source = new BitmapImage(new Uri(photo.Path));
image.Source = source;
}
}
catch(Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex);
}
}
You can find the full examples for CameraCaptureUI, and native android.
Other types of camera capture are currently not implemented (as of Uno 3.0), and you'll need to go through native APIs to use them.

Related

How to enable Platform.runlater within method

I am creating a Javafx chat app which also allows for file transfer. My issue is I open a FileOutputStream for the received file within the below method. I can see my listener.statusTransferring() updating the UI only if I enable Platform.runLater. I think I now need to enable the same on the fos.write(b, 0, tmpTransferred) within the while loop but don't know how to do this. I have tried unsuccessfully wrapping the whole method within Platform runlater. Note: If I don't use platform runlater I don't get any errors however the UI does not update until the file transfer is complete eg listener.statusCompleted() is called;. The error I get now as a result of the fos being in Platform runlater. is below.. Line 185 is fos.write(b, 0, tmpTransferred); The other listener calls appear to work fine. Just not listener.statusTransferring(); or listener.transferUpdate(); which utilise the fos. Any help will be greatly appreciated. Also for your own sanity I am a self taught google programmer. Yep the worst kind I am sure. Thanks in advance.
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at net.thebowdens.net.FileReceiver.transfer(FileReceiver.java:185)
at net.thebowdens.net.DefaultMessageResponder.fileSend(DefaultMessageResponder.java:543)
public boolean transfer() {
listener.statusConnecting();
received = false;
cancel = false;
try {
if (sSock != null) {
sock = sSock.accept();
listener.statusTransferring();
Platform.runLater(() ->{
try {
fos = new FileOutputStream(file);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
});
is = sock.getInputStream();
final byte[] b = new byte[1024];
transferred = 0;
percent = 0;
int tmpTransferred = 0;
int tmpPercent = 0;
int transCounter = 0;
bCounter.prepare();
while (!cancel && (tmpTransferred = is.read(b)) != -1) {
fos.write(b, 0, tmpTransferred);
transferred += tmpTransferred;
percent = (int) ((transferred * 100) / size);
bCounter.addBytes(tmpTransferred);
transCounter++;
if (percent > tmpPercent || transCounter >= 250) {
transCounter = 0;
tmpPercent = percent;
listener.transferUpdate();
}
}
if (!cancel && transferred == size) {
received = true;
listener.statusCompleted();
}
else {
listener.statusFailed();
}
}
}
catch (final IOException e) {
LOG.log(Level.SEVERE, e.toString());
listener.statusFailed();
}
finally {
stopReceiver();
cleanupConnections();
}
return received;
}
Keep in mind that you should use Platform.runLater only for updating the UI, everything else should be outside it otherwhise the UI will become unresponsive.
I suggest you to to refactor your code according to this.
Well after much discussion over the correct language and other issues I solved my problem of the UI updating. I had two issues. My choice selector and Filechooser methods were not on the Javafx application thread (hope this is the right terminology) so I had to do the following:
private ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new Runnable() {
#Override
public void run() {
Platform.runLater(() -> {
try {
receiveRequest(tmpUser, fileRes, user, fileName, size, fileHash);
} catch (IOException | ServerException | CommandException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
});
}
});
I then had to do the same within the Filechooser and file accept method for the transfer class UI to update
executorService.execute(new Runnable() {
#Override public void run() {
if (fileRes.transfer()) {
ui.showSystemMessage("Successfully received " + fileName +
" from " + user + ", and saved as " + fileRes.getFile().getName());
}
else {
ui.showSystemMessage("Failed to receive " + fileName + " from " + user);
fileRes.cancel();
}
}
});
}

Scanning for beacons using universal beacon library

I am trying to implement a mobile app (on iPhone) that just scans for beacons and displays a notification for each one. I am a noob with beacons/bluetooth.
I implemented it using the universal beacon library (https://github.com/andijakl/universal-beacon) and i've attached my ios bluetooth implementation.
my problem is that i receive about 12 beacon added events even though i only have two (I assume it is picking up all my other bluetooth devices). I also only receive the local name in the advertisement_received event.
My questions are:
how do I distinguish that it is a beacon being added?
how do i get the unique id an url from the beacon? (they are kontakt beacons)
Thanks for any help.
My beacon service:
public BeaconService()
{
// get the platform-specific provider
var provider = RootWorkItem.Services.Get<IBluetoothPacketProvider>();
if (null != provider)
{
// create a beacon manager, giving it an invoker to marshal collection changes to the UI thread
_manager = new BeaconManager(provider, Device.BeginInvokeOnMainThread);
_manager.Start();
_manager.BeaconAdded += _manager_BeaconAdded;
provider.AdvertisementPacketReceived += Provider_AdvertisementPacketReceived;
}
}
My ios bluetooth implementation:
public class iOSBluetoothPacketProvider : CocoaBluetoothPacketProvider { }
public class CocoaBluetoothPacketProvider : NSObject, IBluetoothPacketProvider
{
public event EventHandler<BLEAdvertisementPacketArgs> AdvertisementPacketReceived;
public event EventHandler<BTError> WatcherStopped;
private readonly CocoaBluetoothCentralDelegate centralDelegate;
private readonly CBCentralManager central;
public CocoaBluetoothPacketProvider()
{
Debug.WriteLine("BluetoothPacketProvider()");
centralDelegate = new CocoaBluetoothCentralDelegate();
central = new CBCentralManager(centralDelegate, null);
}
private void ScanCallback_OnAdvertisementPacketReceived(object sender, BLEAdvertisementPacketArgs e)
{
AdvertisementPacketReceived?.Invoke(this, e);
}
public void Start()
{
Debug.WriteLine("BluetoothPacketProvider:Start()");
centralDelegate.OnAdvertisementPacketReceived += ScanCallback_OnAdvertisementPacketReceived;
// Wait for the PoweredOn state
//if(CBCentralManagerState.PoweredOn == central.State) {
// central.ScanForPeripherals(peripheralUuids: new CBUUID[] { },
// options: new PeripheralScanningOptions { AllowDuplicatesKey = false });
//}
}
public void Stop()
{
Debug.WriteLine("BluetoothPacketProvider:Stop()");
centralDelegate.OnAdvertisementPacketReceived -= ScanCallback_OnAdvertisementPacketReceived;
central.StopScan();
WatcherStopped?.Invoke(sender: this, e: new BTError(BTError.BluetoothError.Success));
}
}
internal class CocoaBluetoothCentralDelegate : CBCentralManagerDelegate
{
public event EventHandler<BLEAdvertisementPacketArgs> OnAdvertisementPacketReceived;
#region CBCentralManagerDelegate
public override void ConnectedPeripheral(CBCentralManager central, CBPeripheral peripheral)
{
Debug.WriteLine($"ConnectedPeripheral(CBCentralManager central, CBPeripheral {peripheral})");
}
public override void DisconnectedPeripheral(CBCentralManager central, CBPeripheral peripheral, NSError error)
{
Debug.WriteLine($"DisconnectedPeripheral(CBCentralManager central, CBPeripheral {peripheral}, NSError {error})");
}
public override void DiscoveredPeripheral(CBCentralManager central, CBPeripheral peripheral, NSDictionary advertisementData, NSNumber RSSI)
{
Debug.WriteLine($"Cocoa peripheral {peripheral}");
Debug.WriteLine($"Cocoa advertisementData {advertisementData}");
Debug.WriteLine($"Cocoa RSSI {RSSI}");
var bLEAdvertisementPacket = new BLEAdvertisementPacket()
{
Advertisement = new BLEAdvertisement()
{
LocalName = peripheral.Name,
ServiceUuids = new List<Guid>(),
DataSections = new List<BLEAdvertisementDataSection>(),
ManufacturerData = new List<BLEManufacturerData>()
},
AdvertisementType = BLEAdvertisementType.ScanResponse,
BluetoothAddress = (ulong)peripheral.Identifier.GetHashCode(),
RawSignalStrengthInDBm = RSSI.Int16Value,
Timestamp = DateTimeOffset.Now
};
//https://developer.apple.com/documentation/corebluetooth/cbadvertisementdataserviceuuidskey
//if (advertisementData.ContainsKey(CBAdvertisement.DataServiceUUIDsKey))
//{
// bLEAdvertisementPacket.Advertisement.ServiceUuids.Add(
// item: new BLEManufacturerData(packetType: BLEPacketType.UUID16List,
// data: (advertisementData[CBAdvertisement.DataServiceUUIDsKey])));
//}
//https://developer.apple.com/documentation/corebluetooth/cbadvertisementdataservicedatakey
//if (advertisementData.ContainsKey(CBAdvertisement.DataServiceDataKey))
//{
// bLEAdvertisementPacket.Advertisement.DataSections.Add(
// item: new BLEManufacturerData(packetType: BLEPacketType.ServiceData,
// data: advertisementData[CBAdvertisement.DataServiceDataKey]));
//}
//https://developer.apple.com/documentation/corebluetooth/cbadvertisementdatamanufacturerdatakey
if (advertisementData.ContainsKey(CBAdvertisement.DataManufacturerDataKey))
{
bLEAdvertisementPacket.Advertisement.ManufacturerData.Add(
item: new BLEManufacturerData(packetType: BLEPacketType.ManufacturerData,
data: (advertisementData[CBAdvertisement.DataManufacturerDataKey]
as NSData).ToArray()));
}
// Missing CBAdvertisement.DataTxPowerLevelKey
var bLEAdvertisementPacketArgs = new BLEAdvertisementPacketArgs(data: bLEAdvertisementPacket);
OnAdvertisementPacketReceived?.Invoke(this, bLEAdvertisementPacketArgs);
}
public override void FailedToConnectPeripheral(CBCentralManager central, CBPeripheral peripheral, NSError error)
{
Debug.WriteLine($"FailedToConnectPeripheral(CBCentralManager central, CBPeripheral {peripheral}, NSError {error})");
}
public override void UpdatedState(CBCentralManager central)
{
switch (central.State)
{
case CBCentralManagerState.Unknown:
Debug.WriteLine("CBCentralManagerState.Unknown");
break;
case CBCentralManagerState.Resetting:
Debug.WriteLine("CBCentralManagerState.Resetting");
break;
case CBCentralManagerState.Unsupported:
Debug.WriteLine("CBCentralManagerState.Unsupported");
break;
case CBCentralManagerState.Unauthorized:
Debug.WriteLine("CBCentralManagerState.Unauthorized");
break;
case CBCentralManagerState.PoweredOff:
Debug.WriteLine("CBCentralManagerState.PoweredOff");
break;
case CBCentralManagerState.PoweredOn:
Debug.WriteLine("CBCentralManagerState.PoweredOn");
central.ScanForPeripherals(peripheralUuids: new CBUUID[] { },
options: new PeripheralScanningOptions { AllowDuplicatesKey = true });
break;
default:
throw new NotImplementedException();
}
}
public override void WillRestoreState(CBCentralManager central, NSDictionary dict)
{
Debug.WriteLine($"WillRestoreState(CBCentralManager central, NSDictionary {dict})");
}
#endregion CBCentralManagerDelegate
}
So in case anyone is looking for this. The universal beacon library does not have an ios implementation that converts the ios packets to the universal packets. This need to be implemented.
how do I distinguish that it is a beacon being added?
I look for the Eddystone packets and if found I add to the observable list.
how do i get the unique id an url from the beacon? (they are kontakt beacons)
You need to loop through the advertisementData sent with the advertisement and create a BLEAdvertisementDataSection. copy the frame data as NSData.

Xamarin.Forms and Plugin.Media: after about 20 photos something crashes

I have a problem with Xamarin.Forms ver. 2.3.4.224 and Plugin.Media ver. 2.6.2. The problem occurs after taking about 20 photos (depends from the device): basically the app crashes without any apparently reason.
If you want to replicate the error, I created a test project for you on GitHub. With my iPad Air or iPad Pro after about 30 photos (video iPad Air - iPad Pro). All devices are iOS ver. 10.3.1 and they have enough space to storage photos.
The app is very simple: you have two buttons one for taking a picture and the other one to pick a photo. If you take photos one after another, after about 20 (32 in an iPad Air) the app crashes. I'm just take photos with the Plugin.Media nothing more.
Any ideas are welcome.
Update
In my project I had a reference to Refractored.MvvmHelpers and I noticed if I remove it, I can take more pictures. I created my BaseViewModel with INotifyPropertyChanged and I noticed I can take more photos.
I created then a new project (you can find it on GitHub under cameratesteasy) without MVVM and there is just the code to take a photo like:
public partial class cameratesteasyPage : ContentPage
{
int count = 0;
public cameratesteasyPage()
{
InitializeComponent();
CrossMedia.Current.Initialize();
}
void UpdateCount()
{
count++;
CountLabel.Text = $"{count} times";
}
async void StartCameraTapped(object sender, System.EventArgs args)
{
using (var file = await CrossMedia.Current.TakePhotoAsync(
new StoreCameraMediaOptions {}))
{
if (file == null)
return;
UpdateCount();
}
}
async void StartCameraTakeTapped(object sender, System.EventArgs args)
{
var file = await CrossMedia.Current.PickPhotoAsync();
if (file == null)
return;
UpdateCount();
}
}
In this case the app shut down after 52 photos. I saved the log for Xcode and you can see it here.
I used Xamarin Profile and the memory level is always low. After about 30 photos, an error occurs in Xamarin Profiler
Finally I could create a Xamarin Profiler file
Also I noticed this kind of error occurs on iPads. The same app in an iPhone is working fine (apparently) or I didn't find up to now the number of photos before crashing.
Update /2
I decided to implement a native function for taking photo.
Interface
public interface ICamera
{
void TakePicture();
}
Implementation
using System;
using cameratest.iOS;
using Foundation;
using UIKit;
using Xamarin.Forms;
[assembly: Xamarin.Forms.Dependency(typeof(Camera_iOS))]
namespace cameratest.iOS
{
public class Camera_iOS : ICamera
{
static UIImagePickerController picker;
static Action<NSDictionary> _callback;
static void Init()
{
if (picker != null)
return;
picker = new UIImagePickerController();
picker.Delegate = new CameraDelegate();
}
class CameraDelegate : UIImagePickerControllerDelegate
{
public override void FinishedPickingMedia(
UIImagePickerController picker, NSDictionary info)
{
var cb = _callback;
_callback = null;
picker.DismissModalViewController(true);
cb(info);
}
}
public static void TakePicture(UIViewController parent,
Action<NSDictionary> callback)
{
Init();
picker.SourceType = UIImagePickerControllerSourceType.Camera;
_callback = callback;
parent.PresentModalViewController(picker, true);
}
public static void SelectPicture(UIViewController parent,
Action<NSDictionary> callback)
{
Init();
picker.SourceType = UIImagePickerControllerSourceType.PhotoLibrary;
_callback = callback;
parent.PresentModalViewController(picker, true);
}
public void TakePicture()
{
var rc = UIApplication.SharedApplication.KeyWindow.RootViewController;
TakePicture(rc, (obj) =>
{
var photo = obj.ValueForKey(
new NSString("UIImagePickerControllerOriginalImage")) as UIImage;
var documentsDirectory =
Environment.GetFolderPath(Environment.SpecialFolder.Personal);
// hardcoded filename, overwritten each time
string jpgFilename = System.IO.Path.Combine(documentsDirectory,
"Photo.jpg");
NSData imgData = photo.AsJPEG();
NSError err = null;
if (imgData.Save(jpgFilename, false, out err))
{
Console.WriteLine("saved as " + jpgFilename);
}
else
{
Console.WriteLine("NOT saved as " +
jpgFilename + " because" + err.LocalizedDescription);
}
});
}
}
}
With this code after about 30 photos, the app crashes. The only difference is with this code I can receive some alert from ReceiveMemoryWarning. If you have an interest, I updated the code on GitHub.

QR detection using ZXing with Vuforia in Unity

We have implemented the QR detection functionality using ZXing.dll in Unity 5.3.4f1 with Vuforia Unity SDK 5.5.9. We have a QR detection script on GameObject which remains active throughout the app and using below mentioned (QRScanner.cs) code ( as mentioned on Unity Zxing QR code scanner integration ).
We are also using Vuforia for image detection (50 image targets) in the same scene where QR detection is expected. The Vuforia plugin is getting enabled / disabled multiple times as per our requirement. Both the image and QR detection is working perfectly for us on Android and iOS devices until the app is in focus. Whenever VuforiaBehaviour gets disabled and enabled, QR detection stops working after that. QRScanner script always receives null data after the app is resumed or AR camera is reloaded. We have tried keeping our QR detection script on AR camera prefab and also tried
qcarBehaviour.RegisterTrackablesUpdatedCallback(OnTrackablesUpdated);
qcarBehaviour.RegisterQCARStartedCallback(OnTrackablesUpdated);
callbacks every time AR camera starts but with no success. The QR detection stops working completely after pausing Vuforia plugin for any reason.
Does anybody have any idea how to fix this issue?
QRScanner.cs
using UnityEngine;
using System;
using System.Collections;
using Vuforia;
using System.Threading;
using ZXing;
using ZXing.QrCode;
using ZXing.Common;
/* ///////////////// QR detection does not work in editor //////////////// */
[AddComponentMenu("System/QRScanner")]
public class QRScanner : MonoBehaviour
{
private bool cameraInitialized;
private BarcodeReader barCodeReader;
public AppManager camScript;
void Start()
{
barCodeReader = new BarcodeReader();
StartCoroutine(InitializeCamera());
}
private IEnumerator InitializeCamera()
{
// Waiting a little seem to avoid the Vuforia's crashes.
yield return new WaitForSeconds(3f);
var isFrameFormatSet = CameraDevice.Instance.SetFrameFormat(Image.PIXEL_FORMAT.RGB888, true);
Debug.Log(String.Format("FormatSet : {0}", isFrameFormatSet));
// Force autofocus.
// var isAutoFocus = CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
// if (!isAutoFocus)
// {
// CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL);
// }
// Debug.Log(String.Format("AutoFocus : {0}", isAutoFocus));
cameraInitialized = true;
}
private void Update()
{
if (cameraInitialized)
{
try
{
var cameraFeed = CameraDevice.Instance.GetCameraImage(Image.PIXEL_FORMAT.RGB888);
if (cameraFeed == null)
{
return;
}
var data = barCodeReader.Decode(cameraFeed.Pixels, cameraFeed.BufferWidth, cameraFeed.BufferHeight, RGBLuminanceSource.BitmapFormat.RGB24);
if (data != null)
{
// QRCode detected.
Debug.Log(data.Text);
Application.OpenURL (data.Text); // our function to call and pass url as text
data = null; // clear data
}
else
{
Debug.Log("No QR code detected !");
}
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
}
}
}
i have this problem to
but i fix that with place code on ARcam
using UnityEngine;
using System.Collections;
using Vuforia;
public class CameraSettings : MonoBehaviour
{
#region PRIVATE_MEMBERS
private bool mVuforiaStarted = false;
private bool mAutofocusEnabled = true;
private bool mFlashTorchEnabled = false;
private CameraDevice.CameraDirection mActiveDirection = CameraDevice.CameraDirection.CAMERA_DEFAULT;
#endregion //PRIVATE_MEMBERS
#region MONOBEHAVIOUR_METHODS
void Start () {
Debug.Log("CameraSettings Start");
VuforiaAbstractBehaviour vuforia = FindObjectOfType<VuforiaAbstractBehaviour>();
VuforiaARController.Instance.RegisterVuforiaStartedCallback(OnVuforiaStarted);
VuforiaARController.Instance.RegisterOnPauseCallback(OnPaused);
VuforiaARController.Instance.RegisterTrackablesUpdatedCallback (OnTrack);
//VuforiaARController.Instance.RegisterVideoBgEventHandler(BgEventHandler);
}
#endregion // MONOBEHAVIOUR_METHODS
#region PUBLIC_METHODS
public bool IsFlashTorchEnabled()
{
return mFlashTorchEnabled;
}
public void SwitchFlashTorch(bool ON)
{
if (CameraDevice.Instance.SetFlashTorchMode(ON))
{
Debug.Log("Successfully turned flash " + ON);
mFlashTorchEnabled = ON;
}
else
{
Debug.Log("Failed to set the flash torch " + ON);
mFlashTorchEnabled = false;
}
}
public bool IsAutofocusEnabled()
{
return mAutofocusEnabled;
}
public void SwitchAutofocus(bool ON)
{
if (ON)
{
if (CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO))
{
Debug.Log("Successfully enabled continuous autofocus.");
mAutofocusEnabled = true;
}
else
{
// Fallback to normal focus mode
Debug.Log("Failed to enable continuous autofocus, switching to normal focus mode");
mAutofocusEnabled = false;
CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL);
}
}
else
{
Debug.Log("Disabling continuous autofocus (enabling normal focus mode).");
mAutofocusEnabled = false;
CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL);
}
}
public void TriggerAutofocusEvent()
{
// Trigger an autofocus event
CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_TRIGGERAUTO);
// Then restore original focus mode
StartCoroutine(RestoreOriginalFocusMode());
}
public void SelectCamera(CameraDevice.CameraDirection camDir)
{
if (RestartCamera (camDir))
{
mActiveDirection = camDir;
// Upon camera restart, flash is turned off
mFlashTorchEnabled = false;
}
}
public bool IsFrontCameraActive()
{
return (mActiveDirection == CameraDevice.CameraDirection.CAMERA_FRONT);
}
#endregion // PUBLIC_METHODS
#region PRIVATE_METHODS
private void OnTrack() {
//Debug.Log("CameraSettings OnTrack");
}
private void BgEventHandler() {
//Debug.Log("CameraSettings BgEventHandler");
}
private void OnVuforiaStarted() {
//Debug.Log("CameraSettings OnVuforiaStarted");
mVuforiaStarted = true;
// Try enabling continuous autofocus
SwitchAutofocus(true);
//RestartCamera (CameraDevice.CameraDirection.CAMERA_DEFAULT);
}
private void OnPaused(bool paused) {
bool appResumed = !paused;
//Debug.Log("CameraSettings OnPaused");
if (appResumed && mVuforiaStarted)
{
// Restore original focus mode when app is resumed
if (mAutofocusEnabled)
CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
else
CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL);
// Set the torch flag to false on resume (cause the flash torch is switched off by the OS automatically)
mFlashTorchEnabled = false;
}
}
private IEnumerator RestoreOriginalFocusMode()
{
// Wait 1.5 seconds
yield return new WaitForSeconds(1.5f);
// Restore original focus mode
if (mAutofocusEnabled)
CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
else
CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL);
}
private bool RestartCamera(CameraDevice.CameraDirection direction)
{
ObjectTracker tracker = TrackerManager.Instance.GetTracker<ObjectTracker>();
if (tracker != null)
tracker.Stop();
CameraDevice.Instance.Stop();
CameraDevice.Instance.Deinit();
if (!CameraDevice.Instance.Init(direction))
{
Debug.Log("Failed to init camera for direction: " + direction.ToString());
return false;
}
if (!CameraDevice.Instance.Start())
{
Debug.Log("Failed to start camera for direction: " + direction.ToString());
return false;
}
if (tracker != null)
{
if (!tracker.Start())
{
Debug.Log("Failed to restart the Tracker.");
return false;
}
}
return true;
}
#endregion // PRIVATE_METHODS
}

ASP.Net and Parallel.Foreach causes buttons to stop working?

i have a very large database of images from the web which i am categorizing (downloaded locally).
so i have a website (locally) to do this, but the db queries were taking long, so i got an idea to "preload" the next page, so that only the very first load of the page would be slow. I save the list of items loaded in a seperate thread in session. So far so good.
I wanted to optimize further, and did some testing on what took the longest, and loading the images to check the size to see if i needed to scale them (set image height and width on the img obj) - so i wanted to do this with a parallel.foreach loop - but after doing this, my buttons on the page stopped responding? i can see the page runs through the page_load event when i press a button, but it doesn't reach the buttons "code":
protected virtual void btnSaveFollowPosts_Click(object sender, EventArgs e)
{...}
any take on what i am doing wrong? i have tried to limit the degree of paralellelism to 1 just to see if that would fix it - but it did not.
Update - code:
trying to boil it down:
protected void Page_Load(object sender, EventArgs e)
{
Search(false);
}
protected void Search(bool updateCounters)
{
if (Session[SessionItems] == null)
{
if (Session[SessionItemsCache] == null)
{
//if is being constructed, wait, else construct
//if construction is not running
if (Session[SessionCacheConstructionRunning] == null)
{
StartPreLoadContent();
}
while (Session[SessionCacheConstructionRunning] != null)
{
Thread.Sleep(25); //block main thread untill items ready
}
}
List<ContentView> contentViewList = Session[SessionItemsCache] as List<ContentView>;
Session[SessionItemsCache] = null; //clean preload cache
Session[SessionItems] = contentViewList; //save in current usage storage
Filltable(ref tblContent, contentViewList);
//preload next batch
StartPreLoadContent();
}
else
{
List<ContentView> contentViewList = Session[SessionItems] as List<ContentView>; //get items from session
Session[SessionItems] = contentViewList; //save in current usage storage
Filltable(ref tblContent, contentViewList);
}
}
protected void StartPreLoadContent()
{
Session[SessionCacheConstructionRunning] = true;
//start task
Thread obj = new Thread(new ThreadStart(RunPreLoadContent));
obj.IsBackground = true;
obj.Start();
}
protected void RunPreLoadContent()
{
using (DBEntities entities = new DBEntities())
{
entities.CommandTimeout = 86400;
IQueryable<ContentView> query = entities.ContentView.Where(some criterias);
List<ContentView> contentViewListCache = query.ToList();
ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = 7;
Parallel.ForEach(contentViewListCache, options, content =>
{
try
{
Interlocked.Increment(ref imageSizeCount);
string path = Path.Combine(basePath, content.LocalPath);
int imageSize = 150;
using (System.Drawing.Image realImage = System.Drawing.Image.FromFile(path))
{
double scale = 0;
if (realImage.Height > realImage.Width)
{
scale = (double)realImage.Height / imageSize;
}
else
{
scale = (double)realImage.Width / imageSize;
}
if (scale > 1)
{
content.ImageHeight = (int)((double)realImage.Height / scale);
content.ImageWidth = (int)((double)realImage.Width / scale);
content.ImageScaled = true;
}
content.ShowImage = true;
}
}
catch (Exception)
{
}
});
Session[SessionItemsCache] = contentViewListCache;
Session[SessionCacheConstructionRunning] = null; //cache ready
}
protected virtual void btnSave_Click(object sender, EventArgs e)
{
try
{
//save
...some reading and saving going on here...
//update
Session[SessionItems] = null;
Search(true);
}
catch (Exception error)
{
ShowError(error);
}
}
I agree with a previous comment: you should probably do this logic earlier in the page lifecycle. Consider overriding OnInit and putting it there.
Also, you could try this line of code instead of your current thread code (which is more suited to Windows not Web programming):
using System.Threading.Tasks;
Task.Run(() => { RunPreLoadContent(); });

Resources