@Abt: Funktioniert. Perfekt. Besten Dank!
JsonContext.cs
using System.Text.Json.Serialization;
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(WeatherForecast))]
internal partial class SourceGenerationContext : JsonSerializerContext
{
}
Program.cs
using System.Text;
using System.Text.Json;
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
internal class Program
{
static void Main(string[] args)
{
try
{
var weatherForecast = new WeatherForecast()
{
Date = DateTime.Parse("2019-08-01"),
TemperatureCelsius = 25,
Summary = "Hot"
};
var jsonString = JsonSerializer.Serialize(weatherForecast!, SourceGenerationContext.Default.WeatherForecast);
var byteArray = Encoding.UTF8.GetBytes(jsonString);
var restoredJsonString = Encoding.UTF8.GetString(byteArray);
var restoredWeatherForecast = JsonSerializer.Deserialize<WeatherForecast>(restoredJsonString, SourceGenerationContext.Default.WeatherForecast);
Console.WriteLine(restoredWeatherForecast.Summary);
Console.WriteLine(restoredWeatherForecast.TemperatureCelsius);
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.ReadKey();
}
}
Eine Frage hab ich allerdings noch. Was bewirkt das Ausrufezeichen hinter weatherForecast?
var jsonString = JsonSerializer.Serialize(weatherForecast!, SourceGenerationContext.Default.WeatherForecast);
@david.m: Funktioniert auch mit .NET 7.
Ich glaube du hast vergessen in deiner .csproj <PublishAot>true</PublishAot> hinzuzufügen. Bei deinem Quellcode bekomme ich folgenden Output:
Object as Json: {}
Restored Json: {}
Unhandled Exception: System.NotSupportedException: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'WeatherForecast'. Path: $ | LineNumber: 0 | BytePositionInLine: 1.
---> System.NotSupportedException: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'WeatherForecast'.
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ThrowNotSupportedException(ReadStack&, Utf8JsonReader&, NotSupportedException) + 0x33a
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader&, Type, JsonSerializerOptions, ReadStack&, T&) + 0xd3
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader&, Type, JsonSerializerOptions, ReadStack&, T&, Boolean&) + 0x225
at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader&, JsonSerializerOptions, ReadStack&) + 0x350
at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1, JsonTypeInfo`1, Nullable`1) + 0xfe
at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1, JsonTypeInfo`1) + 0x108
at System.Text.Json.JsonSerializer.Deserialize[TValue](String, JsonSerializerOptions) + 0x4c
at Program.Main(String[] args) + 0x11c
at JsonSerializerConsole!<BaseAddress>+0x20ea69
Also irgendwie habe ich glaube ich gerade ein Brett vorm Kopf. Sollte folgendes nicht eigentlich funktionieren?
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
public class WeatherForecast
{
[JsonConstructorAttribute]
public WeatherForecast(DateTimeOffset Date, int TemperatureCelsius, string? Summary)
{
this.Date = Date;
this.TemperatureCelsius = TemperatureCelsius;
this.Summary = Summary;
}
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
internal class Program
{
static void Main(string[] args)
{
try
{
var weatherForecast = new WeatherForecast(DateTime.Parse("2019-08-01"), 25, "Hot");
var jsonString = JsonSerializer.Serialize(weatherForecast);
var byteArray = Encoding.UTF8.GetBytes(jsonString);
var restoredJsonString = Encoding.UTF8.GetString(byteArray);
var restoredWeatherForecast = JsonSerializer.Deserialize<WeatherForecast>(restoredJsonString);
Console.WriteLine(restoredWeatherForecast.Summary);
Console.WriteLine(restoredWeatherForecast.TemperatureCelsius);
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.ReadKey();
}
}
Bekomme aber immer noch folgende Exception:
System.NotSupportedException: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'WeatherForecast'. Path: $ | LineNumber: 0 | BytePositionInLine: 1.
---> System.NotSupportedException: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'WeatherForecast'.
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ThrowNotSupportedException(ReadStack&, Utf8JsonReader&, NotSupportedException) + 0x1fe
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader&, Type, JsonSerializerOptions, ReadStack&, T&) + 0xb2
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader&, Type, JsonSerializerOptions, ReadStack&, T&) + 0x1ec
at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader&, JsonSerializerOptions, ReadStack&) + 0x34f
at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1, JsonTypeInfo, Nullable`1) + 0x109
at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1, JsonTypeInfo) + 0xf5
at System.Text.Json.JsonSerializer.Deserialize[TValue](String, JsonSerializerOptions) + 0x58
at Program.Main(String[]) + 0xe3
@Palladin007: Hmmm ja, das entspricht dann meinem zweiten Ansatz bzw. zweiten Beitrag. Leider funktioniert das auch nicht. Siehst du den Fehler, den ich gemacht habe?
@Abt: Also entweder verstehe ich die Fehlermeldung nicht richtig oder das betrifft quasi jede Art von Konstruktor. Ist also nicht umsetzbar.
Ich habe nochmal was anderes ausprobiert. Leider funktioniert es nur wieder ohne NativeAot.
using System.Text;
using System.Text.Json;
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
internal class Program
{
static void Main(string[] args)
{
try
{
var weatherForecast = new WeatherForecast
{
Date = DateTime.Parse("2019-08-01"),
TemperatureCelsius = 25,
Summary = "Hot"
};
var jsonString = JsonSerializer.Serialize(weatherForecast);
var byteArray = Encoding.UTF8.GetBytes(jsonString);
var restoredJsonString = Encoding.UTF8.GetString(byteArray);
var restoredWeatherForecast = JsonSerializer.Deserialize<WeatherForecast>(restoredJsonString);
Console.WriteLine(restoredWeatherForecast.Summary);
Console.WriteLine(restoredWeatherForecast.TemperatureCelsius);
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.ReadKey();
}
}
Ausgabe IL exe:
Hot
25
Ausgabe native exe:
System.NotSupportedException: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'WeatherForecast'. Path: $ | LineNumber: 0 | BytePositionInLine: 1.
---> System.NotSupportedException: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'WeatherForecast'.
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ThrowNotSupportedException(ReadStack&, Utf8JsonReader&, NotSupportedException) + 0x1fe
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader&, Type, JsonSerializerOptions, ReadStack&, T&) + 0xb2
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader&, Type, JsonSerializerOptions, ReadStack&, T&) + 0x1ec
at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader&, JsonSerializerOptions, ReadStack&) + 0x34f
at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1, JsonTypeInfo, Nullable`1) + 0x109
at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1, JsonTypeInfo) + 0xf5
at System.Text.Json.JsonSerializer.Deserialize[TValue](String, JsonSerializerOptions) + 0x58
at Program.Main(String[]) + 0xe3
Guten Tag zusammen,
ich benötige ein Object als Byte Array und muss dieses auch wieder von einem Byte Array zu einem Object zurückkonvertieren können. Das klingt erstmal nach keinem Problem, allerdings wird das Programm mit NativeAot kompiliert und dann funktioniert es nicht mehr. Hier mein Codeansatz:
BinarySerializer.cs
using System.Runtime.Serialization.Formatters.Binary;
public class BinarySerializer
{
public static byte[] Serialize(object objectToSerialize)
{
var binaryFormatter = new BinaryFormatter();
var memoryStream = new MemoryStream();
binaryFormatter.Serialize(memoryStream, objectToSerialize);
return memoryStream.ToArray();
}
public static object Deserialize(byte[] bytesToDeserialize)
{
var memoryStream = new MemoryStream();
var binaryFormatter = new BinaryFormatter();
memoryStream.Write(bytesToDeserialize, 0, bytesToDeserialize.Length);
memoryStream.Position = 0;
return binaryFormatter.Deserialize(memoryStream);
}
}
Program.cs
[Serializable]
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
internal class Program
{
static void Main(string[] args)
{
try
{
var weatherForecast = new WeatherForecast
{
Date = DateTime.Parse("2019-08-01"),
TemperatureCelsius = 25,
Summary = "Hot"
};
var byteArray = BinarySerializer.Serialize(weatherForecast);
var restoredWeatherForecast = (WeatherForecast)BinarySerializer.Deserialize(byteArray);
Console.WriteLine(restoredWeatherForecast.Summary);
Console.WriteLine(restoredWeatherForecast.TemperatureCelsius);
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.ReadKey();
}
}
.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PublishAot>true</PublishAot>
<EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
Wenn ich nun die IL exe starte. Ausgabe (wie gewünscht):
Hot
25
Wenn ich dann die native exe starte. Ausgabe:
System.TypeInitializationException: A type initializer threw an exception. To determine which type, inspect the InnerException's StackTrace property.
---> System.IO.FileNotFoundException: Cannot load assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. No metadata found for this assembly.
at System.Reflection.Runtime.General.ReflectionCoreCallbacksImplementation.Load(AssemblyName, Boolean) + 0x7d
at System.Runtime.Serialization.Formatters.Binary.Converter..cctor() + 0x2e3
at System.Runtime.CompilerServices.ClassConstructorRunner.EnsureClassConstructorRun(StaticClassConstructionContext*) + 0xc6
--- End of inner exception stack trace ---
at System.Runtime.CompilerServices.ClassConstructorRunner.EnsureClassConstructorRun(StaticClassConstructionContext*) + 0x167
at System.Runtime.CompilerServices.ClassConstructorRunner.CheckStaticClassConstructionReturnGCStaticBase(StaticClassConstructionContext*, Object) + 0xd
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.GetAssemblyId(WriteObjectInfo) + 0x68
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object, BinaryFormatterWriter) + 0x1ed
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream, Object) + 0xef
at BinarySerializer.Serialize(Object) + 0x64
at Program.Main(String[]) + 0x88
Hoffe es gibt da eine Möglichkeit die die gewünschte Funktion mit NativeAot funktional macht. Welchen Klassen am Ende benutzt werden ist ja egal. Hauptsach es läuft. Aber nach Möglichkeit ohne Third Party Libraries. Bin auf eure Antworten gespannt.
Mit freundlichen Grüßen
Naja der Unterschied ist das der Code mit Threads funktioniert, aber nicht mit Tasks. Ich würde dennoch lieber Tasks verwenden, weil Thread.Abort nur im .NET Framework funktioniert und eben eigentlich nicht genutzt werden sollte.
Es handelt sich um ein sehr simples Konstrukt. Es gibt den Hauptthread und eben genau den einen Helferthread. Der Hauptthread teilt sich in 2 Bereiche auf und der Helferthread darf nur in Bereich 2 mitlaufen. Bestimmte Bedingungen in Bereich 2 können dazu führen das der Hauptthread wieder in Bereich 1 übergeht und die ersten Zeilen des Bereich 1 dafür sorgen das der Helferthread gestoppt wird, bis der Hauptthread irgendwann wieder in Bereich 2 übergeht und der Helferthread wieder gestartet wird. Also quasi:
Hauptthread Bereich 1 -> Helferthread gestoppt
Hauptthread Bereich 2 -> Helferthread läuft
Danke für eure Antworten. Im nachfolgenden Beispiel hätte ich genau das was ich bräuchte, nur leider läuft der Code nur mit dem .NET Framework und nicht mit .NET 6 oder 7. Wie würde der Code aussehen, wenn er unter .NET 6 oder 7 laufen würde?
using System;
using System.Threading;
namespace ThreadAbortTest
{
class App
{
private Thread DoesSomethingThread { get; set; } = null;
public void Run()
{
while (true)
{
if (DoesSomethingThread != null)
{
DoesSomethingThread.Abort();
}
DoesSomethingThread = new Thread(() =>
{
while (true)
{
Console.Write("Active!");
Thread.Sleep(5000);
}
});
DoesSomethingThread.Start();
Thread.Sleep(15000);
}
}
}
}
Guten abend,
ich habe einen Codeabschnitt der öfters mal ausgeführt wird und der einen Task startet. Da dieser Abschnitt öfters ausgeführt wird würde er jedesmal einen Task mehr starten. Es soll aber immer nur ein Task gleichzeitig laufen. Leider klappt das canceln des alten Tasks nicht wodurch sich die laufenden Tasks anhäufen. Warum? Freue mich über jede Hilfe.
Hier ein Beispiel:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace CancelTaskTest
{
class App
{
private CancellationTokenSource TaskCancel { get; set; } = new CancellationTokenSource();
public void Run()
{
while (true)
{
TaskCancel.Cancel();
TaskCancel = new CancellationTokenSource();
Task.Run(() =>
{
while (true)
{
Console.Write("Active!");
Thread.Sleep(5000);
if (TaskCancel.Token.IsCancellationRequested)
{
Console.Write("Cancelled!"); // Never gets called, why?
return;
}
}
}, TaskCancel.Token);
Thread.Sleep(15000);
}
}
}
}
Mit freundlichen Grüßen