In Win2d canvasControl , how to call createResources event multiple times whenever needed? - c#

I have a canvasControl,in that CreateResources Event is fired only once when I run the Program.I had a FilePicker to pick an image source from local.Whenever an Image is Picked , i need to Call CreateResources event to load the Resources and then draw it using canvasBitmap and DrawingSession.
I Know how to Draw but,I Don't Know how to Load Resources Whenever an image is picked.Can anyone Suggest me ,how to achieve this??

It's not necessary to load resources in CreateResource event all the time, you can load resources whenever you want (outside of Draw event handler) and then just call Invalidate method. Look at this:
CanvasBitmap btmp;
private async void LoadNecessaryResourcesAndDraw()
{
btmp = await CanvasBitmap.LoadAsync(MyCanvasControl, "some_image.png");
MyCanvasControl.Invalidate(); /// this will invoke the draw event
}
public void MyCanvasControl_Draw(CanvasControl sender, CanvasDrawEventArgs args)
{
if(btmp != null)
{
args.DrawingSession.DrawImage(btmp);
}
}
Now you can call the LoadNecessaryResourcesAndDraw() method anytime. It will load the image asynchronously, then invoke the draw event which will draw the image.

in Win2D, the CreateResource event is only triggered when the CanvasControl is loading, that is, it will only be triggered once.
If you need to create resources after this, you need to create a custom LoadResourcesForLevelAsync method:
async Task LoadResourcesForLevelAsync(CanvasControl resourceCreator, int level)
{
levelBackground = await CanvasBitmap.LoadAsync(resourceCreator, ...);
levelThingie = await CanvasBitmap.LoadAsync(resourceCreator, ...);
// etc.
}
This is explained in the Win2D documentation, please refer to this document:
Loading resources outside of CreateResources
Update
A simple example of loading pictures in the Draw event:
private string imageFilePath = #"ms-appx:///Assets/StoreLogo.png";
private CanvasBitmap img;
private void CanvasControl_Draw(CanvasControl sender, CanvasDrawEventArgs args)
{
if (img != null)
{
args.DrawingSession.DrawImage(img);
}
else
{
GetImage().Wait();
}
async Task GetImage()
{
await Task.Run(async () =>
{
img = await CanvasBitmap.LoadAsync(sender, new Uri(imageFilePath));
}).ConfigureAwait(false);
}
}
Thanks.

Related

How to wait till a task is fully completed?

I have a image processing application in which I have 2 modes. Manual inspection and Automatic inspection using a PLC command.
Manual inspection works fine, the user clicks a button to grab an image, and then clicks another button to process the image and send results to the PLC.
But in automatic inspection mode, im getting incorrect inspection result(same product/image inspection in manual mode gets correct result). I suspect that after grabbing image the system is not getting enough time to read the full image before the inspection starts, so I added a thread.sleep(500), But that didnt make any difference. So I tried the async await.task.delay(500) method, same result.
Is there any other way to fix it?
Code:
private async void timer3_Tick(object sender, EventArgs e)
{
btncheckm1_Click(null, null);
var newSignal = textBox8.Text.Contains("+1");
var isRisingEdge = newSignal && (_oldSignal == false);
_oldSignal = newSignal;
if (isRisingEdge)
{
lblmessages.Text = "";
totalsheetcount++;
btngrabimage_Click(null, null);
// Thread.Sleep(300);
await Task.Delay(1000);
processimage();
}
}
btngrabimage() has the following code:
try
{
camimage = null;
cam1.BeginAcquisition();
// Retrieve an image
IManagedImage rawImage = cam1.GetNextImage();
IManagedImage convertedImage = rawImage.Convert(PixelFormatEnums.Mono8);
imagetoinspect = convertedImage.bitmap;
rawImage.Release();
cam1.EndAcquisition();
//cam1.DeInit();
distort();
}
catch (Exception ee)
{
}
I also would say that wrapping the grabbing of an image inside a task and awaiting that result is the way to go. The image class represents your return type as the image. Dont mind the function names though. Task.Run and Task.Factory.StartNew are essentially the same thing, just wanted to show you have different options for creating your task
public class ImageRetriever
{
public void ProcessImage()
{
//if you would like to get rid of the async
//reminder that calling .Result is blocking for the current thread.
//this means the thread will stop working untill the result is returned
//could be an issue if this is called on UI thead
var imageTask = GetImage();
Image image = imageTask.Result;
}
public async Task ProcessImageAsync()
{
//if you want to keep the async-nonblocking
Image image = await GetImage();
}
private Task<Image> GetImage()
{
//this is how your create your task
Task<Image> imageTask;
imageTask = Task.Run(() =>
{
return new Image();
});
// or
imageTask = Task.Factory.StartNew(() =>
{
return new Image();
});
return imageTask;
}
}
public class Image
{
}

async Memorystream approach in c# to get data async

My dashboard needs too much time to get data from database so I have to use async approach to handle this problem here is my code :
public async Task < Stream > LoadDashboard() {
Stream s = new MemoryStream(Encoding.Default.GetBytes(Resource.Dashboard));
s.Position = 0;
return s;
}
private async void frmMaterialDashboard_Load(object sender, EventArgs e) {
Stream dashboardData = await LoadDashboard();
dashboardViewer1.LoadDashboard(dashboardData);
//show UI components for user interact
}
My code doesn't work and I have to wait for data to come from the database. Should I add anything else ?
This part of code takes long time to load data
Stream s = new MemoryStream(Encoding.Default.GetBytes(Resource.Dashboard));
s.Position = 0;
I want to execute this part async. When my form is loaded I want to call LoadDashboard as a background task to get the data from database ,and the main thread show my user interface form .
The component link that I am using :
https://documentation.devexpress.com/#Dashboard/CustomDocument113927
From what it looks like you have no actual async work you can do, you are reading a resource in to a memory stream. Putting the async keyword on somthing does nothing by itself, the function still runs just like it used to. If you want the work to happen in the background you have to tell it to work in the background by using a new thread.
//Get rid of this async stuff here.
public Stream LoadDashboard()
{
Stream s = new MemoryStream(Encoding.Default.GetBytes(Resource.Dashboard));
s.Position = 0;
return s;
}
private async void frmMaterialDashboard_Load(object sender, EventArgs e)
{
//Start LoadDashboad in a background thread and await it.
Stream dashboardData = await Task.Run(() => LoadDashboard());
dashboardViewer1.LoadDashboard(dashboardData);
//show UI components for user interact
}
Another option is to not copy the string to a memory stream and instead get the stream directly
private void frmMaterialDashboard_Load(object sender, EventArgs e)
{
using (var dashboardStream = Resources.ResourceManager.GetStream("Dashboard"))
{
dashboardViewer1.LoadDashboard(dashboardStream);
}
//show UI components for user interact
}
I got rid of the async because DashboadViewer does not provide a way to call LoadDashboard from the background to the best of my knowledge. You will have to wait till it finishes loading or figure out how to get smaller data.

Capture Image From Camera set to ImageView

How to upload or add an Image to UIImageView directly from iPhone/Ipad Captured camera Image.
I have uploaded an image to UIImageView from photo library.
Now, I want upload an image directly after taken an image through camera to ImageView.
Please suggest me how to implement this.
using IOS 8.0
This can be accomplished very easily with the Xamarin.Mobile component, which is free and works with all platforms.
http://components.xamarin.com/view/xamarin.mobile
From the example they give:
using Xamarin.Media;
// ...
var picker = new MediaPicker ();
if (!picker.IsCameraAvailable)
Console.WriteLine ("No camera!");
else {
try {
MediaFile file = await picker.TakePhotoAsync (new StoreCameraMediaOptions {
Name = "test.jpg",
Directory = "MediaPickerSample"
});
Console.WriteLine (file.Path);
} catch (OperationCanceledException) {
Console.WriteLine ("Canceled");
}
}
After you take the picture, it is saved to the directory you specified, with the name you specified. To easily retrieve this picture and display it with your ImageView using the above example you can do the following:
//file is declared above as type MediaFile
UIImage image = new UIImage(file.Path);
//Fill in with whatever your ImageView is
yourImageView.Image = image;
Edit:
Just a note that the above needs to be asynchronous. So if you want to launch the camera from a button call, for instance, you just slightly modify the .TouchUpInside event:
exampleButton.TouchUpInside += async (object sender, EventArgs e) => {
//Code from above goes in here, make sure you have async after the +=
};
Otherwise you could wrap the code from above in a function and add async to that:
public async void CaptureImage()
{
//Code from above goes here
}
You will need to use AVFoundation to do this. Check out the AVCam sample project in Xcode:
https://developer.apple.com/library/ios/samplecode/AVCam/Introduction/Intro.html

MediaElement Source cannot be set after SaveState/LoadState

(Note: All code has been severely simplified.)
Problem
MediaElement source not being set after Suspend/Resume. The CurrentState quickly changes to "Closed" after the source is set.
I am handling the MediaFailed event — it doesn't fire. I am also handling the MediaOpened event, which doesn't fire either.
Details
I have the following method which updates the MediaElement's Source. It works really well as long as the app is not trying to resume after having been Suspended.
private async void UpdateMediaElementSource(object sender, EventArgs e)
{
var videoSource = this.DefaultViewModel.CurrentSource; // a string
var file = await StorageFile.GetFileFromPathAsync(videoSource);
var videoStream = await file.OpenAsync(FileAccessMode.Read);
this.videoMediaElement.SetSource(videoStream, file.ContentType);
// The above line works many times as long as the app is not trying to Resume.
}
When the app is Suspended it calls the SaveState method:
protected async override void SaveState(Dictionary<String, Object> pageState)
{
pageState["MediaElementSource"] = this.DefaultViewModel.CurrentSource;
// I also made the videoStream global so I can dispose it — but no dice.
this.videoStream.Dispose();
this.videoStream = null;
}
When the app Resumes, it calls the LoadState method:
protected async override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
string source = string.Empty;
if (pageState != null)
{
if (pageState.ContainsKey("MediaElementSource"))
{
source = (string)pageState["MediaElementSource"];
}
}
var document = PublicationService.GetDocument(this.currentDocumentIdNumber);
this.DefaultViewModel = new DocumentViewModel(document);
this.DefaultViewModel.CurrentMarkerSourceChanged += UpdateMediaElementSource;
if (!string.IsNullOrEmpty(source))
{
// This causes the UpdateMediaElementSource() method to run.
this.DefaultViewModel.CurrentSource = source;
}
}
I appreciate any help on this issue. Please let me know if you need more details.
So, it turns out that the mediaElement's Source was being set before it was added to the visual tree.
Usually, this is not an issue when doing this:
mediaElement.Source = whatever;
but it IS an issue when you do this:
mediaElement.SetSource(stream, MimeType);
Conclusion
Make sure that your MediaElement is part of the VisualTree when you call SetSource(...).
A simple way to get my above code to work is by adding a global bool that is set to true once the mediaElement.Loaded event has fired. Then, inside the code that calls SetSource(), wrap that in an if(_mediaElementLoaded) block.

C# show gps location on map

I am working in a windows mobile application and I want to show my current location with google maps. I used the Location dll from the samples. As you see below in my code, I call the proper method for updating the map in the gps_Locationchanged event where I use the Invoke method to update the pictureboxe's image. The problem is that I can't use the main menu and the context menu of the application whenever i want. It's like they freeze until the new map finish downloading. Is there another way to do that in different thread so they can be used anytime?
void gps_LocationChanged(object sender, LocationChangedEventArgs args)
{
if (args.Position.LatitudeValid && args.Position.LongitudeValid)
{
pictureBox1.Invoke((UpdateMap)delegate()
{
center.Latitude = args.Position.Latitude;
center.Longitude = args.Position.Longitude;
LatLongToPixel(center);
image_request2(args.Position.Latitude, args.Position.Longitude);
});
}
}
Maybe something along these lines?
bool m_fetching;
void gps_LocationChanged(object sender, LocationChangedEventArgs args)
{
if (m_fetching) return;
if (args.Position.LatitudeValid && args.Position.LongitudeValid)
{
ThreadPool.QueueUserWorkItem(UpdateProc, args);
}
}
private void UpdateProc(object state)
{
m_fetching = true;
LocationChangedEventArgs args = (LocationChangedEventArgs)state;
try
{
// do this async
var image = image_request2(args.Position.Latitude, args.Position.Longitude);
// now that we have the image, do a synchronous call in the UI
pictureBox1.Invoke((UpdateMap)delegate()
{
center.Latitude = args.Position.Latitude;
center.Longitude = args.Position.Longitude;
LatLongToPixel(center);
image;
});
}
finally
{
m_fetching = false;
}
}
It's hard to say for sure, but it looks like the image_request2() method that (I assume) gets the actual image from the server is the problem. If you were to run this method on a worker thread, and provide a simple callback method that would paint the image on the screen once it's completely downloaded, this would leave your UI thread open to receive events from the user.

Categories