Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
may i find useful answer from you.
I have WPF application fetching the data from API, I have thread deadlock when i fire following code
private List<Clinic> _clinics;
public List<Clinic> Clinics {
get { return _clinics; }
set { _clinics = value; OnPropertyChanged(); }
}
private Clinic _selectedClinic;
public Clinic SelectedClinic {
get { return _selectedClinic; }
set {
_selectedClinic = value; OnPropertyChanged();
if (value != null)
OnSelectClinic(value).Wait();
}
}
private async Task OnSelectClinic(Clinic clinic) {
try {
using (var request = await Client.GetAsync("URL OF API")) {
if (request.IsSuccessStatusCode){
StaffList = await request.Content.ReadAsAsync<Staff>();
}
var error = await request.Content.ReadAsStringAsync();
throw new Exception(error);
}
} catch (Exception e) {
Debug.WriteLine(e);
}
}
this is the view model, and Clinics, selectedClinic and Staff are binding to View.XAML
and here is the API Method
[HttpGet("FindAllByClinic/{clinicId}")]
public async Task<IActionResult> FindAllByClinic(int clinicId) {
try {
return Ok(_mapper.Map<List<Staff>>(await _staffRepository
.FindAllBy(clinicId)));
} catch (Exception e) {
return BadRequest(e.Message);
}
}
Here is StaffRepository method :
public async Task<ICollection<Staff>> FindAllBy(int clinicId, int medicalPointId) {
var persons = await Context.Persons.FromSql("EXEC HR.GetPersonsByClinicId #ClinicId = 0," +
$"#EncryptPassword = '{DecryptPassword}'").ToListAsync();
var staffs = await Context.Staff
.Include(e => e.StaffClinics)
.ThenInclude(e => e.Clinic)
.ThenInclude(e => e.ClinicMedicalPoints)
.Where(e => e.StaffClinics.Any(c => c.ClinicId == clinicId
&& c.Clinic.ClinicMedicalPoints.Any(m => m.MedicalPointId
== medicalPointId)))
.ToListAsync();
foreach (var staff in staffs) {
staff.Person = persons.FirstOrDefault(e => e.Id == staff.PersonId);
}
return staffs;
}
the problem is when i select a clinic from combobox the entire application freeze
Can any one give me suggestions or correct my code if I Have mistakes please
public Clinic SelectedClinic {
get { return _selectedClinic; }
set {
_selectedClinic = value; OnPropertyChanged();
if (value != null)
OnSelectClinic(value).Wait();
}
}
This setter is super bad, because:
It raises an event with OnPropertyChanged - that's okay - but then it continues to perform a costly operation in the setters body. You're already rasing an event, maybe something should subscribe to it and perform the OnSelectClinic instead?
You're blocking on async code, which is a sin that causes deadlocks. Normally the solution is to replace blocking waits with awaits, but in this case you need to redesign so that a property setter is not responsible for firing and awaiting this operation.
Related
I'm analyzing the dump file for the Windows service project, and it is using LinqToSQL to connect databases. Attached dumpe heap memory analysis summary.
I can see the System.Data.Linq.Mapping.AttributedMetaDataMember taking more memory and It's resides in Gen2 bucket.
Can anyone guide me why it's taking more memory here?
Sample Code
public class Program
{
static void Main(string[] args)
{
var detailsDataContext = new DetailsContext();
var details = detailsDataContext.GetDetails(//param);
}
}
public class DetailsContext
{
private readonly IDetailsDataContextRepository _detailsDataContextRepository;
public DetailsContext()
{
_detailsDataContextRepository = new DetailsDataContextRepository();
}
public Details GetDetails(string id)
{
try
{
List<Details> detailsList = _detailsDataContextRepository.GetDetails(id)?.ToList();
if (detailsList != null && detailsList.Count > 0)
{
Detail detail = detailsList.FirstOrDefault();
return detailsList;
}
return null;
}
catch (Exception ex)
{
//Error log
return null;
}
}
}
public class DetailsDataContextRepository : DataContext, IDetailsDataContextRepository
{
[Function(Name = "dbo.sp_GetDetails")]
public IEnumerable<Details> GetDetails([Parameter(Name = "Id", DbType = "VARCHAR(255)")] string id)
{
try
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), id);
ISingleResult<Details> mRecord = ((ISingleResult<Details>)(result.ReturnValue));
return mRecord;
}
catch (Exception ex)
{
TraceError("DetailsDataContext", "GetDetails", ex);
return new List<Details>();
}
}
}
Thanks in Advance.
I'll focus on DetailsContext.GetDetails(string id) method as one example of how to improve things.
Instead of this:
public Details GetDetails(string id)
{
try
{
List<Details> detailsList = _detailsDataContextRepository.GetDetails(id)?.ToList();
if (detailsList != null && detailsList.Count > 0)
{
Detail detail = detailsList.FirstOrDefault();
return detailsList;
}
return null;
}
catch (Exception ex)
{
//Error log
return null;
}
}
You can get equivalent functionality like this:
public Details GetDetails(string id)
{
try
{
return _detailsDataContextRepository.GetDetails(id).FirstOrDefault();
}
catch (Exception ex)
{
//Error log
return null;
}
}
Not only is this MUCH less code, but it's faster and far more memory efficient. As mentioned in the comment, one of the main improvements here is eliminating the spurious ToList() call, which accomplished nothing useful. I see a lot of programmers adopt this crutch, and learning to work without it can dramatically help your code.
Furthermore, based on a review of the repository's GetDetails() method, I might also remove the try/catch block, since that method itself uses a try/catch around anything that's likely to throw and provides a sensible default. It means we can safely get down to this one-liner with no loss of function:
public Details GetDetails(string id)
{
return _detailsDataContextRepository.GetDetails(id).FirstOrDefault();
}
I'm implementing auto complete feature in my .NET MAUI app and I'm using CommunityToolkit.Mvvm code generators in my view model to handle observable properties.
I have the following code and I'm trying call GetSuggestions() method when the SearchText changes.
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(GetSuggestions))]
string searchText;
[ObservableProperty]
bool showSuggestions;
ObservableCollection<string> Suggestions { get; } = new();
private async Task GetSuggestions()
{
if(string.IsNullOrEmpty(SearchText) || SearchText.Length < 3)
return;
var data = await _myApiService.GetSuggestions(SearchText.Trim());
if(data != null && data.Count > 0)
{
Suggestions.Clear();
foreach(var item in data)
Suggestions.Add(item);
ShowSuggestions = true;
}
}
This is giving me the following error:
The target(s) of [NotifyCanExecuteChangedFor] must be an accessible
IRelayCommand property, but "GetSuggestions" has no matches in type
MyViewModel.
What am I doing wrong here?
I guess there are two problems here.
Why is this error occurring?
That happens because GetSuggestions is not a Command.
Try adding the [RelayCommand] attribute to your method.
[RelayCommand]
private async Task GetSuggestions()
{
if(string.IsNullOrEmpty(SearchText) || SearchText.Length < 3)
return;
var data = await _myApiService.GetSuggestions(SearchText.Trim());
if(data != null && data.Count > 0)
{
Suggestions.Clear();
foreach(var item in data)
Suggestions.Add(item);
ShowSuggestions = true;
}
}
Then link NotifyCanExecuteChangedFor to the autogenerated command.
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(GetSuggestionsCommand))]
string searchText;
The second one.
You need to
call GetSuggestions() method when the SearchText changes.
The NotifyCanExecuteChangedFor attribute doesn't do that.
In the autogenerated source code you should find an empty partial method called OnSearchTextPropertyChanged. Try implementing it.
partial void OnSearchTextPropertyChanged(string value)
{
GetSuggestions();
}
If this is what you're searching for, GetSuggestions doesn't need to be marked with the RelayCommand attribute.
Only meant as more of an amendment of #RMinato's answer.
As my comment say: "While most of this was helpful, I need to do a few things different including using the [RelayCommand] and calling the method inside my OnPropChanged method to be Task.Run(() => this.MyMethodAsync()).Wait();".
My code looks like:
[QueryProperty(nameof(Course), nameof(Course))]
public partial class CourseDetailViewModel : BaseViewModel
{
private readonly CourseService courseService;
public CourseDetailViewModel(CourseService courseService)
{
this.courseService = courseService;
}
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(GetCourseDetailCommand))]
Course course;
partial void OnCourseChanged(Course value)
{
Task.Run(() => this.GetCourseDetailAsync()).Wait();
}
[RelayCommand]
public async Task GetCourseDetailAsync()
{
if (GetCourseDetailCommand.IsRunning) return;
try
{
IsBusy = true;
course = await courseService.GetCourseDetailAsync(course.Id);
}
catch (Exception ex)
{
Debug.WriteLine($"Failed to get course detail. Error: {ex.Message}");
await Shell.Current.DisplayAlert("Error!",
$"Failed to get course detail: {ex.Message}", "OK");
throw;
}
finally
{
IsBusy = false;
}
}
}
I'm implementing my own version of auto-complete in a view model in my Xamarin Forms 5 app.
I need to call an async look up function from the Keyword MVVM property. Not sure if I'm handling it right. See below:
string keyword { get; set; }
ObservableRangeCollection<string> suggestions = new ObservableRangeCollection<string>();
public string Keyword
{
get => keyword;
set
{
if(keyword == value)
return;
keyword = value;
OnPropertyChanged();
// If keyword has at least 3 characters, get suggestions
if(keyword.length > 2)
GetSuggestions(keyword).Wait();
}
}
ObservableRangeCollection<string> Suggestions
{
get => suggestions;
set
{
if(sugggestions == value)
return;
suggestions = value;
OnPropertyChanged();
}
}
async Task GetSuggestions(string searchKeyword)
{
var result = await _myApiService.GetSuggestions(searchKeyword);
if(result != null)
{
Suggestions = new ObservableRangeCollection(result);
OnPropertyChanged(Suggestions);
}
}
I'd appreciate any corrections or suggestions. Thanks.
You definitely don't want to block on async code here (as explained on my blog). More generally, you don't want to block the UI, especially when your users are interacting with it (i.e., typing).
Instead, use a pattern like async data binding to (synchronously) start the operation, and then update your UI when the results come in.
E.g., using NotifyTask<T> from here:
string keyword { get; set; }
NotifyTask<List<string>> suggestions;
public string Keyword
{
get => keyword;
set
{
if (keyword == value)
return;
keyword = value;
OnPropertyChanged();
// If keyword has at least 3 characters, get suggestions
if (keyword.length > 2)
suggestions = NotifyTask.Create(GetSuggestionsAsync(keyword));
}
}
NotifyTask<List<string>> Suggestions
{
get => suggestions;
}
async Task<List<string>> GetSuggestionsAsync(string searchKeyword)
{
return await _myApiService.GetSuggestions(searchKeyword);
}
Then, instead of data-binding to Suggestions as a collection of string, data-bind to Suggestions.Result instead. You can also data-bind to Suggestions.IsCompleted (or Suggestions.IsNotCompleted) to show a loading/busy indicator, and Suggestions.IsFaulted to show an error message.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
In case number of nested try-catches happen to be many, e.g. a 100, is there any other way than simply writing 100 nested try-catches in the following manner?
try{
....
} catch(exception ex1)
try{
....
} catch(exception ex2) {
try{
}
....
You're free to nest try/catches multiple levels deep if you want.
try
{
operation1();
}
catch (Exception e)
{
try
{
operation2();
}
catch (Exception e2)
{
// etc
}
}
Given you need to this 100 times and have to use exception for your control flow (which should be avoided if possible). You could use some wrapper, like this:
public class ExWrapper
{
private readonly Action _action;
private readonly ExWrapper _prev;
private ExWrapper(Action action, ExWrapper prev = null)
{
_action = action;
_prev = prev;
}
public static ExWrapper First(Action test)
{
return new ExWrapper(test);
}
public ExWrapper Then(Action test)
{
return new ExWrapper(test, this);
}
public void Execute()
{
if (_prev != null)
try
{
_prev.Execute();
}
catch (Exception)
{
_action();
}
else
_action();
}
}
This allows you to chain actions, where the next action is only executed if the first one throws. You can use it as in the following example:
ExWrapper.First(() => { Console.WriteLine("First"); throw new Exception(); })
.Then( () => { Console.WriteLine("Second"); throw new Exception(); })
.Then( () => { Console.WriteLine("Third"); throw new Exception(); })
.Then( () => { Console.WriteLine("Fourth"); })
.Execute();
This executes all actions or lambdas in the given order, but will only execute the following action if the first throws. The example above prints:
First
Second
Third
Fourth
If you remove the throws in the example:
ExWrapper.First(() => { Console.WriteLine("First"); })
.Then( () => { Console.WriteLine("Second"); })
.Then( () => { Console.WriteLine("Third"); })
.Then( () => { Console.WriteLine("Fourth"); })
.Execute();
Only the first action is executed, resulting in the following output:
First
Just write another try-block inside the catch-block.
try {
//task A
} catch(Exception ex) {
try {
//task B
}
}
Another option would be to move your tasks to methods that return a bool indicating success, and then you don't have to nest your try/catches:
public static bool TrySomething(string someInput)
{
bool result = true;
try
{
// do something with someInput
}
catch
{
result = false;
}
return result;
}
public static bool TrySomethingElse(string someInput)
{
bool result = true;
try
{
// do something with someInput
}
catch
{
result = false;
}
return result;
}
Then in your main code, you could do:
string data = "some data";
if (!TrySomething(data))
{
TrySomethingElse(data);
}
Nested try-catch use a lot of resources and if they get out of hand they can significantly reduce the performance of your program. How ever, you can sequentially add catch blocks:
try
{
//code here
}catch(SomeException ex)
{
//Display what the specific exception was
}catch(SomeOtherException ex)
{
//Display what the specific exception was
}
What'd be the most elegant way to call an async method from a getter or setter in C#?
Here's some pseudo-code to help explain myself.
async Task<IEnumerable> MyAsyncMethod()
{
return await DoSomethingAsync();
}
public IEnumerable MyList
{
get
{
//call MyAsyncMethod() here
}
}
There is no technical reason that async properties are not allowed in C#. It was a purposeful design decision, because "asynchronous properties" is an oxymoron.
Properties should return current values; they should not be kicking off background operations.
Usually, when someone wants an "asynchronous property", what they really want is one of these:
An asynchronous method that returns a value. In this case, change the property to an async method.
A value that can be used in data-binding but must be calculated/retrieved asynchronously. In this case, either use an async factory method for the containing object or use an async InitAsync() method. The data-bound value will be default(T) until the value is calculated/retrieved.
A value that is expensive to create, but should be cached for future use. In this case, use AsyncLazy from my blog or AsyncEx library. This will give you an awaitable property.
Update: I cover asynchronous properties in one of my recent "async OOP" blog posts.
You can't call it asynchronously, since there is no asynchronous property support, only async methods. As such, there are two options, both taking advantage of the fact that asynchronous methods in the CTP are really just a method that returns Task<T> or Task:
// Make the property return a Task<T>
public Task<IEnumerable> MyList
{
get
{
// Just call the method
return MyAsyncMethod();
}
}
Or:
// Make the property blocking
public IEnumerable MyList
{
get
{
// Block via .Result
return MyAsyncMethod().Result;
}
}
I really needed the call to originate from the get method, due to my decoupled architecture. So I came up with the following implementation.
Usage: Title is in a ViewModel or an object you could statically declare as a page resource. Bind to it and the value will get populated without blocking the UI, when getTitle() returns.
string _Title;
public string Title
{
get
{
if (_Title == null)
{
Deployment.Current.Dispatcher.InvokeAsync(async () => { Title = await getTitle(); });
}
return _Title;
}
set
{
if (value != _Title)
{
_Title = value;
RaisePropertyChanged("Title");
}
}
}
You can use Task like this :
public int SelectedTab
{
get => selected_tab;
set
{
selected_tab = value;
new Task(async () =>
{
await newTab.ScaleTo(0.8);
}).Start();
}
}
I think that we can await for the value just returning first null and then get the real value, so in the case of Pure MVVM (PCL project for instance) I think the following is the most elegant solution:
private IEnumerable myList;
public IEnumerable MyList
{
get
{
if(myList == null)
InitializeMyList();
return myList;
}
set
{
myList = value;
NotifyPropertyChanged();
}
}
private async void InitializeMyList()
{
MyList = await AzureService.GetMyList();
}
I thought .GetAwaiter().GetResult() was exactly the solution to this problem, no?
eg:
string _Title;
public string Title
{
get
{
if (_Title == null)
{
_Title = getTitle().GetAwaiter().GetResult();
}
return _Title;
}
set
{
if (value != _Title)
{
_Title = value;
RaisePropertyChanged("Title");
}
}
}
Since your "async property" is in a viewmodel, you could use AsyncMVVM:
class MyViewModel : AsyncBindableBase
{
public string Title
{
get
{
return Property.Get(GetTitleAsync);
}
}
private async Task<string> GetTitleAsync()
{
//...
}
}
It will take care of the synchronization context and property change notification for you.
You can create an event and invoke an event when the property is changed.
Something like this:
private event EventHandler<string> AddressChanged;
public YourClassConstructor(){
AddressChanged += GoogleAddressesViewModel_AddressChanged;
}
private async void GoogleAddressesViewModel_AddressChanged(object sender, string e){
... make your async call
}
private string _addressToSearch;
public string AddressToSearch
{
get { return _addressToSearch; }
set
{
_addressToSearch = value;
AddressChanged.Invoke(this, AddressToSearch);
}
}
When I ran into this problem, trying to run an async method synchronicity from either a setter or a constructor got me into a deadlock on the UI thread, and using an event handler required too many changes in the general design.
The solution was, as often is, to just write explicitly what I wanted to happen implicitly, which was to have another thread handle the operation and to get the main thread to wait for it to finish:
string someValue=null;
var t = new Thread(() =>someValue = SomeAsyncMethod().Result);
t.Start();
t.Join();
You could argue that I abuse the framework, but it works.
Necromancing.
In .NET Core/NetStandard2, you can use Nito.AsyncEx.AsyncContext.Run instead of System.Windows.Threading.Dispatcher.InvokeAsync:
class AsyncPropertyTest
{
private static async System.Threading.Tasks.Task<int> GetInt(string text)
{
await System.Threading.Tasks.Task.Delay(2000);
System.Threading.Thread.Sleep(2000);
return int.Parse(text);
}
public static int MyProperty
{
get
{
int x = 0;
// https://stackoverflow.com/questions/6602244/how-to-call-an-async-method-from-a-getter-or-setter
// https://stackoverflow.com/questions/41748335/net-dispatcher-for-net-core
// https://github.com/StephenCleary/AsyncEx
Nito.AsyncEx.AsyncContext.Run(async delegate ()
{
x = await GetInt("123");
});
return x;
}
}
public static void Test()
{
System.Console.WriteLine(System.DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss.fff"));
System.Console.WriteLine(MyProperty);
System.Console.WriteLine(System.DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss.fff"));
}
}
If you simply chose System.Threading.Tasks.Task.Run or System.Threading.Tasks.Task<int>.Run, then it wouldn't work.
I think my example below may follow #Stephen-Cleary 's approach but I wanted to give a coded example. This is for use in a data binding context for example Xamarin.
The constructor of the class - or indeed the setter of another property on which it is dependent - may call an async void that will populate the property on completion of the task without the need for an await or block. When it finally gets a value it will update your UI via the NotifyPropertyChanged mechanism.
I'm not certain about any side effects of calling a aysnc void from a constructor. Perhaps a commenter will elaborate on error handling etc.
class MainPageViewModel : INotifyPropertyChanged
{
IEnumerable myList;
public event PropertyChangedEventHandler PropertyChanged;
public MainPageViewModel()
{
MyAsyncMethod()
}
public IEnumerable MyList
{
set
{
if (myList != value)
{
myList = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("MyList"));
}
}
}
get
{
return myList;
}
}
async void MyAsyncMethod()
{
MyList = await DoSomethingAsync();
}
}
I review all answer but all have a performance issue.
for example in :
string _Title;
public string Title
{
get
{
if (_Title == null)
{
Deployment.Current.Dispatcher.InvokeAsync(async () => { Title = await getTitle(); });
}
return _Title;
}
set
{
if (value != _Title)
{
_Title = value;
RaisePropertyChanged("Title");
}
}
}
Deployment.Current.Dispatcher.InvokeAsync(async () => { Title = await getTitle(); });
use dispatcher which is not a good answer.
but there is a simple solution, just do it:
string _Title;
public string Title
{
get
{
if (_Title == null)
{
Task.Run(()=>
{
_Title = getTitle();
RaisePropertyChanged("Title");
});
return;
}
return _Title;
}
set
{
if (value != _Title)
{
_Title = value;
RaisePropertyChanged("Title");
}
}
}
You can change the proerty to Task<IEnumerable>
and do something like:
get
{
Task<IEnumerable>.Run(async()=>{
return await getMyList();
});
}
and use it like
await MyList;