I am getting below exception
System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
in Xamarin Forms UWP while doing await Task.Deley(500);
canvas.DrawCircle(point.Item1.X, point.Item1.Y, 10, dotPaint
private async void OnPainting(object sender, SKPaintSurfaceEventArgs e)
{
var canvas = e.Surface.Canvas;
// scale the canvas up (for higher resolution screens)
var scale = e.Info.Width / (float)Width;
canvas.Scale(scale);
// make the surface nice
canvas.Clear(SKColors.White);
// draw the dots
var dotPaint = new SKPaint
{
IsAntialias = true,
Style = SKPaintStyle.Fill
};
foreach (var point in points)
{
await Task.Delay(500);
dotPaint.Color = point.Item2;
canvas.DrawCircle(point.Item1.X, point.Item1.Y, 10, dotPaint);
}
// draw the instructions
var textPaint = new SKPaint
{
IsAntialias = true,
Color = SKColors.Brown,
Style = SKPaintStyle.Fill,
TextSize = 48,
TextAlign = SKTextAlign.Center,
Typeface = SKTypeface.FromFamilyName("Arial", SKTypefaceStyle.Bold)
};
canvas.DrawText("tap 4 dots!", (float)Width / 2, 50, textPaint);
// give it a border
textPaint.Style = SKPaintStyle.Stroke;
textPaint.StrokeWidth = 1;
textPaint.Color = SKColors.White;
canvas.DrawText("tap 4 dots!", (float)Width / 2, 50, textPaint);
}
It is the await... you can't await in the paint method as the entire method needs to happen in a single go. If it awaits, then the canvas will be destroyed before the await is finished.
Basically, the paint operation is a UI step, and the await part causes the control to leave the UI, during which the paint is seen as done by the OS.
For this type of operation - animation - you might have to have a state and a collection of circles:
// to start the animation (field)
int counter = 0;
```csharp
// then start the animation
Task.Run(async () =>
{
// loop through the points
while (points.Count > counter)
{
await Task.Delay(500);
// ask the UI to repaint
Device.BeginInvokeOnMainThread(() =>
{
counter++;
canvasView.InvalidateSurface();
});
}
});
```csharp
// change the for loop to do this (note the .Take method)
foreach (var point in points.Take(counter))
{
...
}
What you are doing here is to actually "perform the animation" in a counter, and then only drawing the dots so far. This way the paint method runs to completion. After each "animation" step, request a repaint.
I have started using this library from today only and it's looks promising. Is it completed for using in Xamarin Forms? Because I am having difficulty finding small examples/tutorials for Xamarin Forms.
Thanks.
It is fully functional in Forms. There is a "big" forms sample here: https://github.com/mono/SkiaSharp/tree/master/samples/FormsSample
This particular issue has nothing to do with SkiaSharp directly, it is more the actual memory you are writing to is being discarded when you await. If you were using the native platform bits, this will still occur.
The difficulty is that this is a fairly new library - the managed binding. As time goes on, more and more tutorials will appear.
There is also this simple app: https://github.com/mattleibow/SkiaSharpDemo
And the blog to go with it: https://blog.xamarin.com/drawing-with-skiasharp/
@mattleibow Thanks for the samples. Its like magic added to Xamarin Forms. So many design possibility's are open.
https://github.com/mono/SkiaSharp/tree/master/samples/FormsSample
https://github.com/mattleibow/SkiaSharpDemo.
Most helpful comment
It is the await... you can't await in the paint method as the entire method needs to happen in a single go. If it awaits, then the canvas will be destroyed before the await is finished.
Basically, the paint operation is a UI step, and the await part causes the control to leave the UI, during which the paint is seen as done by the OS.
For this type of operation - animation - you might have to have a state and a collection of circles:
```csharp
// then start the animation
Task.Run(async () =>
{
// loop through the points
while (points.Count > counter)
{
await Task.Delay(500);
});
What you are doing here is to actually "perform the animation" in a counter, and then only drawing the dots so far. This way the paint method runs to completion. After each "animation" step, request a repaint.