-1

How to use _Asyn methods correctly ?

With my limited experience with C#, I don't know why. How to improve it? Thanks in advance.

//use : 
 this.SyncDataDataGridView.DataSource = await patentLaunch.LoadAccessDbListAsync();


//Method-01 winfroms UI OK (use ToList() )
    public async Task<List<SyncNotice>> LoadAccessDbListAsync01()
    {

        return await Task.Run(() =>
        {
            using (var context = new SyncDbContextContext())
            {
                return context.SyncNotices.OrderByDescending(m => m.Id).Take(1000).ToList();
            }

        });
    }

    //Method-02 winfroms UI freeze !  ( use  ToListAsync()  EntityFrameworkCore )
    public Task<List<SyncNotice>> LoadAccessDbListAsync02()
    {
        using (var context = new SyncDbContextContext())
        {
            return context.SyncNotices.OrderByDescending(m => m.Id).Take(1000).ToListAsync();
        }

    }

my full code is:

private async void Form_Load(object sender, EventArgs e){
//init binding 
 await  context.SyncNotices.LoadAsync();
 this.SyncDataDataGridView.DataSource = context.SyncNotices.Local.ToBindingList();
}

//init event
patentLaunch.OnFolderAddAccessOk += () => {

                Invoke(new Action(async () =>
                {
                    this.SyncDataDataGridView.DataSource = await patentLaunch.LoadAccessDbListAsync02();

                }));

            };
        };
}  

//call in  fileSystemWatcher1_Created(object sender, System.IO.FileSystemEventArgs e)
//in patentLaunch.cs
public void AddSigleFloderToAccessDb(string folder, string syncStatus)
        {
     
            var now = DateTime.Now;

            var entity = new SyncNotice
            {
                FolderName = folder,
                CreateTime = now,
                SyncStatus = syncStatus

            };


            using (var context = new SyncDbContextContext())
            {

                context.SyncNotices.Add(entity);
                context.SaveChanges();
            }

            UpdateLastExecTime(now);
           // send event
            OnFolderAddAccessOk();

        }

//in patentLaunch.cs
public event Action OnFolderAddAccessOk;

Thanks for JonasH . Thank you for your reply. ,finally I used mehtod01

Some databases do not support truly async queries. In that case queries may be synchronous even if there is a *Async-method.

I have not found any concrete documentation about access supporting or not supporting asynchronous queries. But based on its age, and the fact that your call is actually blocking, I would guess the chances are low.

So as far as I know you just have to use LoadAccessDbListAsync01 to avoid blocking.

zy_sun
  • 175
  • 1
  • 11
  • 1
    Do you mean you cannot add `async` to the second method and `return await ...` the result? Isn't the first method working for your? What are you actually asking? If it's better to Task.Run() a synch method or just await an async one? Or are you experimenting in async/await *elision*? – Jimi Aug 13 '21 at 07:54
  • @Jimi i want to use xxxAsyn methods, like ToListAsync. Don't want me to start the thread by myself. I add async and await to mehtod02 but UI freeze too. – zy_sun Aug 13 '21 at 08:04
  • Show entire button click handler, i.e. full and reproducible sample. – mtkachenko Aug 13 '21 at 08:09
  • Well, give some context to the code you're showing. What is `SyncDbContextContext()`? Do you have sync work there? Where are you setting the DataSource of your DataGridView? You removed that part. In the first method, all work is off-loaded to a ThreadPool Thread. See also: [WPF UI blocking while awaiting DbContext](https://stackoverflow.com/q/32835391/7444103) -- [EF Data Context - Async/Await & Multithreading](https://stackoverflow.com/q/20946677/7444103) – Jimi Aug 13 '21 at 08:26
  • How many items are you trying to load into your grid? – Caius Jard Aug 13 '21 at 08:31
  • Hint: when the Stack Overflow quality checker says you should add more context, trying to work around it by adding garbage indicates that you don't care about the quality of your question. – Jon Skeet Aug 13 '21 at 08:34
  • So, you have an un-synchronized FileSystemWatcher that you try to synchronize with the UI Thread with a sync invocation, while you're awaiting `void` what's possibly sync work, to load a DataGridView. I'm surprised you didn't get a dealock already. -- What happens if you / someone suddenly closes that Form? – Jimi Aug 13 '21 at 08:45
  • @Jimi Thank you for your answer, and sorry that my English is not very good. I think its fileSystemWatcher1_Created is run in the UI thread, which is synchronous. (I printed the thread id in fileSystemWatcher1_Created same as FormsUI_Load ) fileSystemWatcher is a winforms control – zy_sun Aug 13 '21 at 08:54
  • @JonSkeet Thanks for your reminder. In fact, I added a lot of code comments, but stackoverflow does not recognize – zy_sun Aug 13 '21 at 08:58
  • Code comments are okay, but providing context as *text* outside the code is more useful. – Jon Skeet Aug 13 '21 at 09:05
  • A FileSystemWatcher is synchronized only when you set its `SynchronizingObject` property to an UI element. But, you should not do that, unless you just need to change, say, the text of a Label. If you need to perform heavy work, you need to off-load the work to another Thread, to avoid blocking the UI Thread or the Event Handler (you cannot do that, you'll fill up the buffer and start losing events). So, don't `Invoke()`, that's synchronous. -- You then need a delegate that holds the UI's SycnhronizationContext (usually an `IProgress` delegate) to finally set an UI element with the data. – Jimi Aug 13 '21 at 09:05
  • I suggest to test your async methods in a clean Solution, where you just experiment with database queries, to set the DataSource of some Controls, without all that clutter you have around right now. -- If you have sync work, as it appears to be, you need to `Task.Run()` that work: you can only await methods that are actually awaitable, other non-async work done in the same context won't become asynchronous by magic. I.e., in the first method of the original post, all work is done in ThreadPool Thread, in the second, the first call is probably sync, the second, `ToListAsync()`, maybe. – Jimi Aug 13 '21 at 09:10
  • @CaiusJard Thank you for your answer, About 500 counts data one to one to add it. upload my full code – zy_sun Aug 13 '21 at 09:23
  • @mtkachenko Thank you for your answer, upload my full code – zy_sun Aug 13 '21 at 09:23

1 Answers1

2

Some databases do not support truly async queries. In that case queries may be synchronous even if there is a *Async-method.

I have not found any concrete documentation about access supporting or not supporting asynchronous queries. But based on its age, and the fact that your call is actually blocking, I would guess the chances are low.

So as far as I know you just have to use LoadAccessDbListAsync01 to avoid blocking.

JonasH
  • 28,608
  • 2
  • 10
  • 23
  • Thank you for your answer. Does this mean that all "Async-method" are not credible ? Is there a way to quickly identify invalid "Async-method" functions? – zy_sun Aug 16 '21 at 06:06
  • @孙泽洋 You can not rely on all async method returning quickly. Even if the method do work asynchronously, it is possible that it is preseeded by synchronous work. There is no reliable way to determine the actual behavior of methods, async or otherwise, other than reading the documentation, testing and reading the source, if available. – JonasH Aug 16 '21 at 06:18