none
async / await / task RRS feed

  • Question

  • Hello,
    Is good for understanding. Does anyone have the complete example?
    I use a class for that.
    await Task.WhenAll(eggsTask, baconTask, toastTask);
    await Task.Any(eggsTask, baconTask, toastTask);
    or with ManualResetEvent
    
    namespace TaskThreadAwait01
    {
    	class Program
    	{
    		// https://docs.microsoft.com/de-de/dotnet/csharp/programming-guide/concepts/async/
    
    		public class BaseCoffee
    		{
    
    		}
    
    		public class PourCoffee : BaseCoffee
    		{
    
    		}
    
    		public class Toast
    		{
    
    		}
    
    		public class Eggs
    		{
    
    		}
    
    
    		public class Working
    		{
    			public async Task Test()
    			{
    				PourCoffee cup = new PourCoffee();
    
    				Console.WriteLine("coffee is ready");
    				var eggsTask = FryEggsAsync(12);
    				var toastTask = MakeToastWithButterAndJamAsync(20);
    
    				var allTasks = new List<Task> { toastTask };
    				while (allTasks.Any())
    				{
    					Task finished = await Task.WhenAny(allTasks);
    					if (finished == eggsTask)
    					{
    						Console.WriteLine("eggs are ready");
    					}
    					else if (finished == toastTask)
    					{
    						Console.WriteLine("toast is ready");
    					}
    					allTasks.Remove(finished);
    				}
    
    				//Juice oj = PourOJ();
    				Console.WriteLine("oj is ready");
    				Console.WriteLine("Breakfast is ready!");            
    			}
    
    			async Task<Eggs> FryEggsAsync(int number)
    			{
    				Eggs myEggs = new Eggs();
    				await Task.Delay(number * 1000);
    				return myEggs;
    			}
    
    			async Task<Toast> ToastBreadAsync(int number)
    			{
    				Toast myToast = new Toast();
    				await Task.Delay(number * 1000);
    				return myToast;
    			}
    
    			async Task<Toast> MakeToastWithButterAndJamAsync(int number)
    			{
    				var toast = await ToastBreadAsync(number);
    
    				ApplyButter(toast);
    				//ApplyJam(toast);
    				return toast;
    			}
    
    			public void ApplyButter(Toast toast)
    			{
    			   // await Task.Delay(number * 1000);
    			}
    		}
    
    		static void Main(string[] args)
    		{
    			Working t1 = new Working();
    			t1.Test().Wait();
    		}
    	}

    Greetings Markus

    Monday, February 10, 2020 5:25 PM

Answers

  • OK, but what is the best way?

          - Task.WaitAll -> is clear I understand.

          - ManualResetEvent

          - await

          - AutoResetEvent

    Can you show that for the variants? name the advantages and disadvantages?

         

    Thanks in advance.

     

    Best regards Markus

    Take the example of AutoResetEvent:

    class Program { static AutoResetEvent autoResetEvent = new AutoResetEvent(false); static string dataFromServer = ""; static void Main(string[] args) { Task task = Task.Factory.StartNew(() => { GetDataFromServer(); }); //Put the current thread into waiting state until it receives the signal autoResetEvent.WaitOne(); //Thread got the signal Console.WriteLine(dataFromServer); } static void GetDataFromServer() { //Calling any webservice to get data Thread.Sleep(TimeSpan.FromSeconds(4)); dataFromServer = "Webservice data";

    autoResetEvent.Set(); } }

    Notice that the last statement——This will automatically set the state of AutoResetEvent's state to false, so that you can reuse the class instance by calling "WaitOne()" again in somewhere else. However, if you use ManualResetEvent, you MUST ADD "manualResetEvent.Reset()" at the back of:

    autoResetEvent.WaitOne();

    Because ManualResetEvent WON'T set the state to false, which means for ManulResetEvent,

    you have to set the state by calling "Reset()" manually.


    Reproduce your quesions with ScreenToGif is your choice. 
    For IIS: IIS Forum
    For WebSite of .NET: ASP.NET Forum
    For others: StackExchange
    For spam-sender or forum urgent issues, Send your Email at:  forumsfeedback@microsoft.com

    • Marked as answer by Markus Freitag Monday, February 17, 2020 11:55 AM
    Saturday, February 15, 2020 2:37 AM
  • The key word "await" has NOTHING TO DO directly with "ManualResetEvent" and "AutoResetEvent". It's ONLY a symbol to tell the compiler that the Task instance should be working in the async mode. 

    Now a typical example is that:

    public Task<int> SlowWork()
    {
       return Task.Run(()=>{……});
    }
    
    public async Task CallSlowTask()
    {
       // 1. Call the async code, let it run for a while in another thread (Task) in the async mode. The work is usually very slow
      var runningTask = SlowWork();
    
      // 2. Here we can run the sync code, it will block the UI or main thread, so please make them as simple and fast as possible.
      ……
    
     // 3. After this, when we wanna get the result from SlowWork(), we can use await to force that we want to fetch the result. Because "SlowWork()" has been running for a while, maybe the result comes in. But if the result doesn't come in yet, it wil wait in the async mode (NOT blocking the current main thread)
      var result = await runningTask;
    }


    Reproduce your quesions with ScreenToGif is your choice. 
    For IIS: IIS Forum
    For WebSite of .NET: ASP.NET Forum
    For others: StackExchange
    For spam-sender or forum urgent issues, Send your Email at:  forumsfeedback@microsoft.com

    • Marked as answer by Markus Freitag Monday, February 17, 2020 11:55 AM
    Saturday, February 15, 2020 2:45 AM
  • >Visual Studio (2019 or later):

    OK, I have only VS2017.

    For private use,Community version VS 2019 is enough. It's TOTALLY FREE.


    Reproduce your quesions with ScreenToGif is your choice. 
    For IIS: IIS Forum
    For WebSite of .NET: ASP.NET Forum
    For others: StackExchange
    For spam-sender or forum urgent issues, Send your Email at:  forumsfeedback@microsoft.com


    Monday, February 17, 2020 12:54 AM

All replies

  • If the intent is to have task and wait on them check out a simple example which has two task and uses Task.WaitAll I have here, otherwise best to start with a smaller code sample.

    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Monday, February 10, 2020 6:47 PM
    Moderator
  • Hi Markus,

    Thank you for posting here.

    Could you please tell us what version of C# and Visual Studio you are using? Because according to the error message of your second link, it seems that this error is caused by the C# version is too old.

    Best Regards,

    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, February 11, 2020 5:39 AM
  • Hi Timon,

    I use Visual Studio 2017 Prof. 

    Version 15.9.6

    Is too old?

    What is the best way for that version?

    Greetings Markus

    Tuesday, February 11, 2020 6:39 AM
  • Hi Karen, 

    Thanks.

    Reference missing.

    Microsoft.office.core

    Microsoft.office.interop.excel

    I haven't SQL server.

    Is there a way to run your sample easy?

    Greetings Markus

    Tuesday, February 11, 2020 7:02 AM
  • Hi Markus,

    When I run your code with Visual Studio 2019 and .net Framework 4.7.2, it works well.

    Maybe you can try to update your Visual Studio.

    Best Regards,

    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, February 11, 2020 9:05 AM
  • Hi Karen, 

    Thanks.

    Reference missing.

    Microsoft.office.core

    Microsoft.office.interop.excel

    I haven't SQL server.

    Is there a way to run your sample easy?

    Greetings Markus

    Here I placed everything you need into a single form, it needs one button named WaitAllButton, one TextBox named textBox1. The text file can be downloaded in the link shown in the code.

    Does not need any of the references you listed. If the code below does not work perhaps you are in a lower version of the .NET Framework.

    using System;
    using System.IO;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace WindowsFormsApp1
    {
        public partial class Form1 : Form
        {
            private CancellationTokenSource _cancellationTokenSource =
                new CancellationTokenSource();
            public Form1()
            {
                InitializeComponent();
            }
    
            private async void WaitAllButton_Click(object sender, EventArgs e)
            {
                // https://github.com/karenpayneoregon/AsynchronousSharp/blob/master/CodeSnippets/Names1.txt
                var fileName1 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Names1.txt");
    
                if (!File.Exists(fileName1))
                {
                    MessageBox.Show("Failed to find file, please ensure the file exists.");
                    return;
                }
    
                var personArgs1 = new PersonArguments()
                {
                    FileName = fileName1,
                    FirstName = "Rebecca",
                    LastName = "Clark"
                };
    
                var progress = new Progress<string>(value => textBox1.AppendText($"{value}{Environment.NewLine}"));
                var operations = new ShortSamples();
                await Task.Run(() => operations.Example1Async(personArgs1, progress));
            }
        }
        public class Person
        {
            public int Id { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public string Gender { get; set; }
            public DateTime Birthday { get; set; }
        }
        public class PersonArguments
        {
            /// <summary>
            /// File to read
            /// </summary>
            public string FileName { get; set; }
            /// <summary>
            /// First name to find
            /// </summary>
            public string FirstName { get; set; }
            /// <summary>
            /// Last name to find
            /// </summary>
            public string LastName { get; set; }
        }
        /// <summary>
        /// Custom event for reporting progress in async operations
        /// </summary>
        public class ProcessIndexingArgs : EventArgs
        {
            protected int Index;
    
            public ProcessIndexingArgs(int sender)
            {
                Index = sender;
            }
            public int Value => Index;
    
            public override string ToString()
            {
                return Index.ToString();
            }
        }
        public class ShortSamples
        {
            CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
            CancellationToken _cancellationToken = new CancellationToken();
    
            public async Task Example1Async(PersonArguments personArguments, IProgress<string> progress)
            {
                Task<Person> taskOne = await Task.Factory.StartNew(async () =>
                {
                    var person = new Person() { Id = -1 };
    
                    var lines = File.ReadAllLines(personArguments.FileName);
                    for (var index = 0; index < lines.Length - 1; index++)
                    {
                        var lineParts = lines[index].Split(',');
                        if (lineParts[1] == personArguments.FirstName && lineParts[2] == personArguments.LastName)
                        {
                            person.Id = Convert.ToInt32(lineParts[0]);
                            person.Birthday = DateTime.Parse(lineParts[4]);
                            if (lineParts[3] == "1" || lineParts[3] == "2")
                            {
                                person.Gender = lineParts[3] == "1" ? "Female" : "Male";
                            }
                            progress.Report($"Id is {lineParts[0]}");
                            break;
                        }
    
                        await Task.Delay(1, _cancellationToken);
                    }
    
                    progress.Report("Task 1 complete");
                    return person;
    
                }, _cancellationToken);
    
                var taskTwo = await Task.Factory.StartNew(async () =>
                {
                    for (var index = 0; index < 5; index++)
                    {
                        _cancellationToken.ThrowIfCancellationRequested();
                        progress.Report(index.ToString());
    
                        await Task.Delay(12, _cancellationToken);
    
                        _cancellationToken.WaitHandle.WaitOne(500);
                    }
    
                    progress.Report("Task 2 complete");
                    return true;
    
                }, _cancellationToken);
    
                Task.WaitAll(taskOne, taskTwo);
                progress.Report("Both task done!");
    
    
                var personResult = taskOne.Result;
    
                progress.Report(personResult.Id > -1 ?
                    $"Birthday: {personResult.Birthday:d} - gender: {personResult.Gender}" :
                    $"Not found");
            }
        }
    }
    


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Tuesday, February 11, 2020 1:25 PM
    Moderator
  • Hello Karen,

    Thank you very much, it works well.
    Why you used. 

    await Task.Run(() => operations.Example1Async(personArgs1, progress));

    Here you use.

    Task<Person> taskOne = await Task.Factory.StartNew(async () =>
    {
       var person = new Person() { Id = -1 };

    Can you say something about the concept, background.

    Thanks in advance.

    With best regards Markus

    Wednesday, February 12, 2020 5:37 PM
  • Hi Markus Freitag:

    1) This sample given by you isn't complete, and for full runnable sample, please download this WPF version instead at:https://docs.microsoft.com/zh-cn/samples/dotnet/samples/async-and-await-cs/

    2) Let's turn to your questions:

    await Task.Run(() => operations.Example1Async(personArgs1, progress));

    This means you will asynchronously wait for the result of Task when the task itself finishes its own work, your screen such as UI WON'T be blocked.

    @Kareninstructor:Sorry but just a reminder——according to your codes at "Example1Async",I think you don't need to use await for the two tasks, because you have "Task.WaitAll(taskOne, taskTwo);", which means both of the async methods are running until they all finish their own work.

     public async Task Example1Async(PersonArguments personArguments, IProgress<string> progress)
            {
                Task<Person> taskOne = Task.Factory.StartNew(async () =>
                {
                    var person = new Person() { Id = -1 };
    
                    var lines = File.ReadAllLines(personArguments.FileName);
                    for (var index = 0; index < lines.Length - 1; index++)
                    {
                        var lineParts = lines[index].Split(',');
                        if (lineParts[1] == personArguments.FirstName && lineParts[2] == personArguments.LastName)
                        {
                            person.Id = Convert.ToInt32(lineParts[0]);
                            person.Birthday = DateTime.Parse(lineParts[4]);
                            if (lineParts[3] == "1" || lineParts[3] == "2")
                            {
                                person.Gender = lineParts[3] == "1" ? "Female" : "Male";
                            }
                            progress.Report($"Id is {lineParts[0]}");
                            break;
                        }
    
                        await Task.Delay(1, _cancellationToken);
                    }
    
                    progress.Report("Task 1 complete");
                    return person;
    
                }, _cancellationToken);
    
                var taskTwo = Task.Factory.StartNew(async () =>
                {
                    for (var index = 0; index < 5; index++)
                    {
                        _cancellationToken.ThrowIfCancellationRequested();
                        progress.Report(index.ToString());
    
                        await Task.Delay(12, _cancellationToken);
    
                        _cancellationToken.WaitHandle.WaitOne(500);
                    }
    
                    progress.Report("Task 2 complete");
                    return true;
    
                }, _cancellationToken);
    
                Task.WaitAll(taskOne, taskTwo);
                progress.Report("Both task done!");


    Reproduce your quesions with ScreenToGif is your choice. 
    For IIS: IIS Forum
    For WebSite of .NET: ASP.NET Forum
    For others: StackExchange
    For spam-sender or forum urgent issues, Send your Email at:  forumsfeedback@microsoft.com



    Thursday, February 13, 2020 6:05 AM
  • Hi ThankfulHeart,

    Thanks for the response.

    The project is empty. Do you have the full project?

    is empty! You can see it here!

     Do you know an example where I see the possibilities, what is possible for synchronization?
        With --> Task.WaitAll(taskOne, taskTwo); I have it. See below.
     With ManualResetEvent
     With AutoResetEvent
    I find it difficult to read and if the code gets longer, even more complicated. Can I write it more structured?
    Like this.
    public async Task Example1Async(PersonArguments personArguments, IProgress<string> progress)
    {
    	Task<Person> taskOne = Task.Factory.StartNew(async () =>
    	{
    	    Function1();
    	}
    	var taskTwo = Task.Factory.StartNew(async () =>
    	{
    	   Function2();
    	}
    	Task.WaitAll(taskOne, taskTwo);
    	progress.Report("Both task done!");
    }

    How should I write function 1 and 2 correctly, the transfer parameters?
    Can you publish a concrete example?

    public async Task Example1Async(PersonArguments personArguments, IProgress<string> progress)
    {
    	Task<Person> taskOne = Task.Factory.StartNew(async () =>
    	{
    		var person = new Person() { Id = -1 };
    
    		var lines = File.ReadAllLines(personArguments.FileName);
    		for (var index = 0; index < lines.Length - 1; index++)
    		{
    			var lineParts = lines[index].Split(',');
    			if (lineParts[1] == personArguments.FirstName && lineParts[2] == personArguments.LastName)
    			{
    				person.Id = Convert.ToInt32(lineParts[0]);
    				person.Birthday = DateTime.Parse(lineParts[4]);
    				if (lineParts[3] == "1" || lineParts[3] == "2")
    				{
    					person.Gender = lineParts[3] == "1" ? "Female" : "Male";
    				}
    				progress.Report($"Id is {lineParts[0]}");
    				break;
    			}
    
    			await Task.Delay(1, _cancellationToken);
    		}
    
    		progress.Report("Task 1 complete");
    		return person;
    
    	}, _cancellationToken);
    
    	var taskTwo = Task.Factory.StartNew(async () =>
    	{
    		for (var index = 0; index < 5; index++)
    		{
    			_cancellationToken.ThrowIfCancellationRequested();
    			progress.Report(index.ToString());
    
    			await Task.Delay(12, _cancellationToken);
    
    			_cancellationToken.WaitHandle.WaitOne(500);
    		}
    
    		progress.Report("Task 2 complete");
    		return true;
    
    	}, _cancellationToken);
    
    	Task.WaitAll(taskOne, taskTwo);
    	progress.Report("Both task done!");
    
    
    /////////// M

    My goal is this

    my goal!
    I have an assembly line that produces a product and continues in the process sequence.
    It may only continue if the sub-processes that are executed in parallel are finished.
    How can I implement this well?
    Can you give me ideas

    public void Step1()
    {
    	public void SubStep1_1()
    	{
    	
    	}
    	
    	public void SubStep1_2()
    	{
    	
    	}  
    }
    
    public void Step2()
    {
    	public void SubStep2_1()
    	{
    	
    	}
    	
    	public void SubStep2_2()
    	{
    	
    	}  
    }
    
    while (!UserPressStop)
    {
    	public void Controller()
    	{
    		Step1();
    		Step2();
    		Task.WaitAll(taskOne, taskTwo);
    		progress.Report("Both task done!");
    	}
    }
    • What is the best way?
        - Task.WaitAll
        - ManualResetEvent
        - await
        -  ??
        
         Thanks in advance.
    Best regards Markus

    Thursday, February 13, 2020 5:42 PM
  • Markus Freitag:

    About the sample, please follow the rules here:

    Building the sample

    To download and run the sample, follow these steps:

    1. Download and unzip the sample.

    2. In Visual Studio (2019 or later):

      1. On the menu bar, choose File > Open > Project/Solution.

      2. Navigate to the folder that holds the unzipped sample code, and open the c# project (.csproj) file.


    Reproduce your quesions with ScreenToGif is your choice. 
    For IIS: IIS Forum
    For WebSite of .NET: ASP.NET Forum
    For others: StackExchange
    For spam-sender or forum urgent issues, Send your Email at:  forumsfeedback@microsoft.com


    Friday, February 14, 2020 1:29 AM
  • Markus Freitag:

    For 2nd question, maybe Task.WaitAll is OK, but please notice that you should make sure the two tasks WON'T effect each other, they WON'T have common-shared data...ect, because they are running in parallel.

    I'm NOT VERY SURE whether you are running with something like Producing-Consuming, if yes, maybe you have to use something like TDL (Task Data Library).


    Reproduce your quesions with ScreenToGif is your choice. 
    For IIS: IIS Forum
    For WebSite of .NET: ASP.NET Forum
    For others: StackExchange
    For spam-sender or forum urgent issues, Send your Email at:  forumsfeedback@microsoft.com

    Friday, February 14, 2020 1:35 AM
  • >Visual Studio (2019 or later):

    OK, I have only VS2017.

    Friday, February 14, 2020 6:45 AM
  • >For 2nd question, maybe Task.WaitAll is OK

    Can you create a short sample to see it please?

    Thanks.

    Greetings Markus

    Friday, February 14, 2020 6:49 AM
  • public Task Step1() { return Task.Run (……); } public Task Step2() { return Task.Run (……); }

    // Some other class or method... while (!UserPressStop) { public void Controller() { Step1(); Step2(); Task.WaitAll(taskOne, taskTwo); progress.Report("Both task done!"); } }



    Reproduce your quesions with ScreenToGif is your choice. 
    For IIS: IIS Forum
    For WebSite of .NET: ASP.NET Forum
    For others: StackExchange
    For spam-sender or forum urgent issues, Send your Email at:  forumsfeedback@microsoft.com

    Friday, February 14, 2020 7:31 AM
  • OK, but what is the best way?

          - Task.WaitAll -> is clear I understand.

          - ManualResetEvent

          - await

          - AutoResetEvent

    Can you show that for the variants? name the advantages and disadvantages?

         

    Thanks in advance.

     

    Best regards Markus

    Friday, February 14, 2020 4:18 PM
  • OK, but what is the best way?

          - Task.WaitAll -> is clear I understand.

          - ManualResetEvent

          - await

          - AutoResetEvent

    Can you show that for the variants? name the advantages and disadvantages?

         

    Thanks in advance.

     

    Best regards Markus

    Take the example of AutoResetEvent:

    class Program { static AutoResetEvent autoResetEvent = new AutoResetEvent(false); static string dataFromServer = ""; static void Main(string[] args) { Task task = Task.Factory.StartNew(() => { GetDataFromServer(); }); //Put the current thread into waiting state until it receives the signal autoResetEvent.WaitOne(); //Thread got the signal Console.WriteLine(dataFromServer); } static void GetDataFromServer() { //Calling any webservice to get data Thread.Sleep(TimeSpan.FromSeconds(4)); dataFromServer = "Webservice data";

    autoResetEvent.Set(); } }

    Notice that the last statement——This will automatically set the state of AutoResetEvent's state to false, so that you can reuse the class instance by calling "WaitOne()" again in somewhere else. However, if you use ManualResetEvent, you MUST ADD "manualResetEvent.Reset()" at the back of:

    autoResetEvent.WaitOne();

    Because ManualResetEvent WON'T set the state to false, which means for ManulResetEvent,

    you have to set the state by calling "Reset()" manually.


    Reproduce your quesions with ScreenToGif is your choice. 
    For IIS: IIS Forum
    For WebSite of .NET: ASP.NET Forum
    For others: StackExchange
    For spam-sender or forum urgent issues, Send your Email at:  forumsfeedback@microsoft.com

    • Marked as answer by Markus Freitag Monday, February 17, 2020 11:55 AM
    Saturday, February 15, 2020 2:37 AM
  • The key word "await" has NOTHING TO DO directly with "ManualResetEvent" and "AutoResetEvent". It's ONLY a symbol to tell the compiler that the Task instance should be working in the async mode. 

    Now a typical example is that:

    public Task<int> SlowWork()
    {
       return Task.Run(()=>{……});
    }
    
    public async Task CallSlowTask()
    {
       // 1. Call the async code, let it run for a while in another thread (Task) in the async mode. The work is usually very slow
      var runningTask = SlowWork();
    
      // 2. Here we can run the sync code, it will block the UI or main thread, so please make them as simple and fast as possible.
      ……
    
     // 3. After this, when we wanna get the result from SlowWork(), we can use await to force that we want to fetch the result. Because "SlowWork()" has been running for a while, maybe the result comes in. But if the result doesn't come in yet, it wil wait in the async mode (NOT blocking the current main thread)
      var result = await runningTask;
    }


    Reproduce your quesions with ScreenToGif is your choice. 
    For IIS: IIS Forum
    For WebSite of .NET: ASP.NET Forum
    For others: StackExchange
    For spam-sender or forum urgent issues, Send your Email at:  forumsfeedback@microsoft.com

    • Marked as answer by Markus Freitag Monday, February 17, 2020 11:55 AM
    Saturday, February 15, 2020 2:45 AM
  • >Visual Studio (2019 or later):

    OK, I have only VS2017.

    For private use,Community version VS 2019 is enough. It's TOTALLY FREE.


    Reproduce your quesions with ScreenToGif is your choice. 
    For IIS: IIS Forum
    For WebSite of .NET: ASP.NET Forum
    For others: StackExchange
    For spam-sender or forum urgent issues, Send your Email at:  forumsfeedback@microsoft.com


    Monday, February 17, 2020 12:54 AM