当前位置:网站首页>C synchronous asynchronous callback state machine async await demo
C synchronous asynchronous callback state machine async await demo
2022-07-24 20:56:00 【biyusr】
Source code
https://gitee.com/s0611163/AsyncAwaitDemo
Why study this ?
The client and server of our project communicate with WCF, I just wanted to , Can I call... Asynchronously WCF Service? ? Or can it be used async await Method call WCF Service? ?
Then I found out WCF It's through BeginXXX and EndXXX This callback method realizes asynchronous , Doesn't seem to support async await Grammatical sugar , That can only be achieved through the state machine , Otherwise, multiple requests will be written as callback hell .
If you use Task.Run wrap up , Write another one inside Wait, This is pseudoasynchrony , It's better not to use asynchronous , Write in the original non asynchronous way .
After studying callbacks and state machines , Read the relevant blog again , As a blog said , call WCF It's not hard to , Asynchronous call WCF It's not hard to , Asynchronous call WCF And it is not difficult to ensure the calling sequence , The difficulty is that after realizing these , Readability and maintainability of code .
So my conclusion is , call WCF, If there is no special need , It's better not to be asynchronous , It's complicated to write .
C# Sync asynchronous Callback State machine async await Demo
It mainly demonstrates not using async、await Grammatical sugar , Realize asynchrony through callback function and state machine
Why write this Demo?
To help understand asynchrony ,async、await Compiled state machine code , It's a little complicated. , This Demo A relatively simple state machine code is written in , Easy to understand
Code instructions
The code mainly writes three examples of downloading files
Download files synchronously , To prevent the interface from getting stuck when downloading large files , The code executes in a thread , Before the file download is complete , Always occupy a thread
Download files asynchronously , Used async、await Grammatical sugar , When downloading files , You can see ,workerThreads( Number of available threads ) and completionPortThreads( Number of available asynchronous threads ) Will change , But it won't occupy a thread for a long time
Download files asynchronously , Don't use async、await Grammatical sugar , Through callback function and state machine ,workerThreads( Number of available threads ) and completionPortThreads( Number of available asynchronous threads ) Will change , But it won't occupy a thread for a long time
Conclusion : The essence of asynchrony is callback , Asynchrony is the syntax sugar of callback
Compared with synchronous mode , When downloading files asynchronously , Ignore the error , Download speed is not faster , The main advantage of asynchrony is that it does not occupy a thread for a long time
In the absence of async、await Grammar sugar time , Asynchrony can also be achieved using callback functions and state machines , But the code is not elegant enough , Heavy mental burden , therefore async、await Another advantage of is that it makes the code simple
The essence of asynchrony is callback ,C# The asynchronous bottom layer is realized through system level callback and state machine ,async、await Will be compiled into state machine code , Related to using code generator to generate code , But if the code is written by itself , Heavy mental burden
Don't use async、await Under the premise of grammar sugar , Using state machine can avoid callback hell
Even if you don't use async、await Grammatical sugar , I still feel the intrusiveness of asynchrony , There is no way to completely encapsulate it at the bottom , The code intrudes into the event of the control , Use async、await It's also , You start at the bottom of the code , Write async Write all the way to the event layer of the control
reflection :
After testing ,button4_Click、button5_Click、button6_Click When downloading large files , Longer time consuming , But the interface won't get stuck , You can still drag the form freely or click other buttons
button4_Click、button5_Click、button6_Click Method calls AsyncFunctionWithCallback Method
AsyncFunctionWithCallback Method is called HttpUtil Class HttpDownloadFileAsyncWithCallback Method
Please observe the above method carefully , They don't use new Thread、Task.Run、Task.Factory.StartNew And other thread related methods ,
That is to say, perform long-term operations , No blocking interface , But there is no thread ,
In fact, during the process of downloading files , Not used C# Of CLR Thread pool , When testing ,workerThreads The quantity will not change , But you'll see completionPortThreads Quantity change ,
The process of downloading files uses asynchronous thread pool , But when downloading large files , It will not occupy the asynchronous thread pool for a long time
Demo Screenshot

Test code Form1.cs
using Models;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Utils;
namespace AsyncAwaitDemo
{
public partial class Form1 : Form
{
private DateTime _dt1;
private System.Timers.Timer _timer;
private string _testFileDownloadUrl = "http://desk-fd.zol-img.com.cn/t_s1920x1080c5/g6/M00/06/00/ChMkKWHXqV-IJFpUAEJatCdq_LUAAXW8AA1PvwAQlrM029.jpg?downfile=1642227460763.jpg"; // File download test URL
//private string _testFileDownloadUrl = "https://down21.xiazaidb.com/app/xiaomanghe.apk"; // File download test URL
//private string _testFileDownloadUrl = "https://codeload.github.com/0611163/DBHelper/zip/refs/heads/master"; // File download test URL
//private string _testFileDownloadUrl = "http://down-ww5.537a.com/soft/3/ce/com.yhong.muchun_51982ada.apk"; // File download test URL
//private string _testFileDownloadUrl = "https://dl.360safe.com/netunion/20140425/360se+191727+n3f07b78190.exe"; // File download test URL A larger file
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// The timer will use a thread in the thread pool
_timer = new System.Timers.Timer();
_timer.Interval = 100;
_timer.Elapsed += _timer_Elapsed;
_timer.Start();
}
#region Log
private void Log(string log)
{
if (!this.IsDisposed)
{
string msg = DateTime.Now.ToString("mm:ss.fff") + " " + log + "\r\n\r\n";
if (this.InvokeRequired)
{
this.BeginInvoke(new Action(() =>
{
textBox1.AppendText(msg);
}));
}
else
{
textBox1.AppendText(msg);
}
}
}
#endregion
#region _timer_Elapsed
private void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
int workerThreads;
int completionPortThreads;
int maxWorkerThreads;
int maxCompletionPortThreads;
ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);
ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxCompletionPortThreads);
this.BeginInvoke(new Action(() =>
{
label1.Text = " The number of threads currently used by the program :" + (maxWorkerThreads - workerThreads) + " workerThreads:" + workerThreads.ToString() + " completionPortThreads:" + completionPortThreads;
}));
}
#endregion
#region button1_Click Test synchronization method
private void button1_Click(object sender, EventArgs e)
{
Task.Run(() => // Downloading files is a time-consuming operation , Need to execute in thread , Otherwise, the interface is stuck
{
Log(" Start ");
DateTime dt = DateTime.Now;
// Input parameters
string arg1 = "1";
string arg2 = "2";
string arg3 = "3";
// Method call
string result1 = SyncFunction(arg1);
string result2 = SyncFunction(arg2);
string result3 = SyncFunction(arg3);
// Output results
Log(result1);
Log(result2);
Log(result3);
Log(" end , Time consuming :" + DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000"));
});
}
#endregion
#region button2_Click Test asynchronous methods ( Three asynchronous methods are parallel , Output... In sequence )
private async void button2_Click(object sender, EventArgs e)
{
Log(" Start ");
DateTime dt = DateTime.Now;
// Input parameters
string arg1 = "1";
string arg2 = "2";
string arg3 = "3";
// Method call
var t1 = AsyncFunction(arg1);
var t2 = AsyncFunction(arg2);
var t3 = AsyncFunction(arg3);
string result1 = await t1;
string result2 = await t2;
string result3 = await t3;
// Output results
Log(result1);
Log(result2);
Log(result3);
Log(" end , Time consuming :" + DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000"));
}
#endregion
#region button3_Click Test asynchronous methods ( Three asynchronous methods execute sequentially , Output... In sequence )
private async void button3_Click(object sender, EventArgs e)
{
Log(" Start ");
DateTime dt = DateTime.Now;
// Input parameters
string arg1 = "1";
string arg2 = "2";
string arg3 = "3";
// Method call
string result1 = await AsyncFunction(arg1);
string result2 = await AsyncFunction(arg2);
string result3 = await AsyncFunction(arg3);
// Output results
Log(result1);
Log(result2);
Log(result3);
Log(" end , Time consuming :" + DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000"));
}
#endregion
#region button4_Click Test state machine ( Three asynchronous methods execute sequentially , Output... In sequence )( Equivalent to button3_Click)
private void button4_Click(object sender, EventArgs e)
{
List<object> resultList = new List<object>();
// Callback 、 State machine , Don't use async await Grammatical sugar
Action<int, object> awaitAction = null;
awaitAction = (state, result) =>
{
// Input parameters
string arg1 = "1";
string arg2 = "2";
string arg3 = "3";
// Method call
if (state == 0)
{
Log(" Start ");
_dt1 = DateTime.Now;
AsyncFunctionWithCallback(arg1, r => awaitAction(1, r));
return;
}
if (state == 1)
{
resultList.Add(result);
AsyncFunctionWithCallback(arg2, r => awaitAction(2, r));
return;
}
if (state == 2)
{
resultList.Add(result);
AsyncFunctionWithCallback(arg3, r => awaitAction(3, r));
return;
}
// Output results
if (state == 3)
{
resultList.Add(result);
foreach (object item in resultList)
{
Log(item != null ? item.ToString() : "null");
}
Log(" end , Time consuming :" + DateTime.Now.Subtract(_dt1).TotalSeconds.ToString("0.000"));
return;
}
};
awaitAction(0, null);
}
#endregion
#region button5_Click Test state machine ( Three asynchronous methods are parallel , Output... In sequence )( Equivalent to button2_Click)
private void button5_Click(object sender, EventArgs e)
{
object[] resultArray = new object[3];
// Whether the callback function has been called
bool _completedCalled = false;
// lock
object _lock = new object();
// Output results
Action<object[]> output = arr =>
{
if (arr.Count(a => a != null) == 3)
{
lock (_lock)
{
if (!_completedCalled)
{
_completedCalled = true;
foreach (object item in arr)
{
Log(item != null ? item.ToString() : "null");
}
Log(" end , Time consuming :" + DateTime.Now.Subtract(_dt1).TotalSeconds.ToString("0.000"));
}
}
}
};
// Callback 、 State machine , Don't use async await Grammatical sugar
Action<int, object> awaitAction = null;
awaitAction = (state, result) =>
{
// Input parameters
string arg1 = "1";
string arg2 = "2";
string arg3 = "3";
// Method call
if (state == 0)
{
Log(" Start ");
_dt1 = DateTime.Now;
AsyncFunctionWithCallback(arg1, r => awaitAction(1, r));
AsyncFunctionWithCallback(arg2, r => awaitAction(2, r));
AsyncFunctionWithCallback(arg3, r => awaitAction(3, r));
return;
}
// Output results
if (state == 1)
{
resultArray[0] = result;
output(resultArray);
return;
}
if (state == 2)
{
resultArray[1] = result;
output(resultArray);
return;
}
if (state == 3)
{
resultArray[2] = result;
output(resultArray);
return;
}
};
awaitAction(0, null);
}
#endregion
#region button6_Click Test state machine ( Three asynchronous methods are parallel , Output... In sequence )( Equivalent to button2_Click)( be relative to button5_Click More elegant implementation )
private void button6_Click(object sender, EventArgs e)
{
Log(" Start ");
DateTime dt = DateTime.Now;
// Input parameters
string arg1 = "1";
string arg2 = "2";
string arg3 = "3";
// Operating results
object result1 = null;
object result2 = null;
object result3 = null;
// Method call
Await await = new Await();
await.Add(() => AsyncFunctionWithCallback(arg1, r => await.Collect(r, out result1)))
.Add(() => AsyncFunctionWithCallback(arg2, r => await.Collect(r, out result2)))
.Add(() => AsyncFunctionWithCallback(arg3, r => await.Collect(r, out result3)))
.Completed(resultList => // Output results
{
Log(result1 != null ? result1.ToString() : "null");
Log(result2 != null ? result2.ToString() : "null");
Log(result3 != null ? result3.ToString() : "null");
Log(" end , Time consuming :" + DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000"));
})
.Start();
}
#endregion
#region button7_Click Do not use state machines , Execute asynchronous methods with callbacks ( It's basically equivalent to button1_Click)
private void button7_Click(object sender, EventArgs e)
{
Task.Run(() =>
{
Log(" Start ");
DateTime dt = DateTime.Now;
// Input parameters
string arg1 = "1";
string arg2 = "2";
string arg3 = "3";
// Operating results
object result1 = null;
object result2 = null;
object result3 = null;
// Method call
AsyncFunctionWithCallback(arg1, r => result1 = r);
AsyncFunctionWithCallback(arg2, r => result2 = r);
AsyncFunctionWithCallback(arg3, r => result3 = r);
// Wait for all three operation results to return , Before returning the results of the three operations , Always occupy a thread
while (result1 == null || result2 == null || result3 == null)
{
Thread.Sleep(1);
}
// Output results
Log(result1 != null ? result1.ToString() : "null");
Log(result2 != null ? result2.ToString() : "null");
Log(result3 != null ? result3.ToString() : "null");
Log(" end , Time consuming :" + DateTime.Now.Subtract(dt).TotalSeconds.ToString("0.000"));
});
}
#endregion
#region Synchronization method
/// <summary>
/// Synchronization method
/// </summary>
private string SyncFunction(string arg)
{
MemoryStream ms = HttpUtil.HttpDownloadFile(_testFileDownloadUrl);
return " Synchronization method arg=" + arg + " Length of byte array of downloaded file =" + ms.Length;
}
#endregion
#region Asynchronous methods
/// <summary>
/// Asynchronous methods
/// </summary>
private async Task<string> AsyncFunction(string arg)
{
MemoryStream ms = await HttpUtil.HttpDownloadFileAsync(_testFileDownloadUrl);
return " Asynchronous methods arg=" + arg + " Length of byte array of downloaded file =" + ms.Length;
}
#endregion
#region Asynchronous method with callback
/// <summary>
/// Asynchronous method with callback
/// </summary>
/// <param name="arg"> Pass in the parameter </param>
/// <param name="callback"> Callback </param>
/// <param name="nextState"> Next state </param>
private void AsyncFunctionWithCallback(string arg, Action<object> callback)
{
HttpUtil.HttpDownloadFileAsyncWithCallback(_testFileDownloadUrl, new HttpUtilAsyncState() { State = 0 }, obj =>
{
if (obj is Exception)
{
Exception ex = obj as Exception;
Log(" error :" + ex.Message);
}
else
{
MemoryStream ms = obj as MemoryStream;
string result = " Asynchronous method with callback arg=" + arg + " Length of byte array of downloaded file =" + ms.Length;
callback(result);
}
});
}
#endregion
#region use Task Analog asynchronous method
/*
#region Asynchronous methods
/// <summary>
/// Asynchronous methods
/// </summary>
private Task<string> AsyncFunction(string arg)
{
return Task.Run<string>(() =>
{
Thread.Sleep(2000);
return " Asynchronous methods arg=" + arg;
});
}
#endregion
#region Asynchronous method with callback
/// <summary>
/// Asynchronous method with callback
/// </summary>
/// <param name="arg"> Pass in the parameter </param>
/// <param name="callback"> Callback </param>
/// <param name="nextState"> Next state </param>
private void AsyncFunctionWithCallback(string arg, Action<object> callback)
{
Task.Run(() =>
{
if (arg == "1")
{
Thread.Sleep(2000);
}
else
{
Thread.Sleep(2000);
}
string result = " Asynchronous method with callback arg=" + arg;
callback(result);
});
}
#endregion
*/
#endregion
}
}
Asynchronous tool class Await.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Utils
{
/// <summary>
/// Asynchronous tool class
/// Instead of async await Grammatical sugar
/// </summary>
public class Await
{
/// <summary>
/// state
/// </summary>
private int _state { get; set; }
/// <summary>
/// Set of asynchronous operations
/// </summary>
private List<Action> _actionList = new List<Action>();
/// <summary>
/// Operation result set
/// </summary>
private List<object> _resultList = new List<object>();
/// <summary>
/// Callback after completion
/// </summary>
private Action<List<object>> _completedCallback;
/// <summary>
/// Whether the callback function has been called
/// </summary>
private bool _completedCalled = false;
/// <summary>
/// lock
/// </summary>
private object _lock = new object();
/// <summary>
/// Asynchronous tool class Constructors
/// </summary>
public Await()
{
_state = 0;
}
/// <summary>
/// Add an asynchronous operation
/// </summary>
public Await Add(Action action)
{
_actionList.Add(action);
return this;
}
/// <summary>
/// Start execution
/// </summary>
public Await Start()
{
foreach (Action action in _actionList)
{
action();
}
return this;
}
/// <summary>
/// Collect results
/// </summary>
public Await Collect(object result, out object outResult)
{
outResult = result;
_resultList.Add(result);
lock (_lock)
{
_state++;
if (_state == _actionList.Count && _completedCallback != null && !_completedCalled)
{
_completedCalled = true;
_completedCallback(_resultList);
}
}
return this;
}
/// <summary>
/// Callback function after registration
/// </summary>
public Await Completed(Action<List<object>> completedCallback)
{
this._completedCallback = completedCallback;
return this;
}
}
}
File download tool class HttpUtil.cs
The following code uses three ways to download files
Realize file download in synchronous mode
Asynchronously realize file download
Asynchronous download through callback and state machine
using Models;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Utils
{
/// <summary>
/// Http Upload and download files
/// </summary>
public class HttpUtil
{
#region HttpDownloadFile Download the file
/// <summary>
/// Download the file
/// </summary>
/// <param name="url"> Download the file url route </param>
/// <param name="cookie">cookie</param>
public static MemoryStream HttpDownloadFile(string url, CookieContainer cookie = null, WebHeaderCollection headers = null)
{
try
{
// Set parameters
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "GET";
request.CookieContainer = cookie;
if (headers != null)
{
foreach (string key in headers.Keys)
{
request.Headers.Add(key, headers[key]);
}
}
// Send the request and get the corresponding response data
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
// until request.GetResponse() The program starts to send to the target web page Post request
Stream responseStream = response.GetResponseStream();
// Create a write stream
MemoryStream stream = new MemoryStream();
byte[] bArr = new byte[10240];
int size = responseStream.Read(bArr, 0, (int)bArr.Length);
while (size > 0)
{
stream.Write(bArr, 0, size);
size = responseStream.Read(bArr, 0, (int)bArr.Length);
}
stream.Seek(0, SeekOrigin.Begin);
responseStream.Close();
return stream;
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
#region HttpDownloadFile Download the file ( asynchronous )
/// <summary>
/// Download the file
/// </summary>
/// <param name="url"> Download the file url route </param>
/// <param name="cookie">cookie</param>
public static async Task<MemoryStream> HttpDownloadFileAsync(string url, CookieContainer cookie = null, WebHeaderCollection headers = null)
{
try
{
// Set parameters
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "GET";
request.CookieContainer = cookie;
if (headers != null)
{
foreach (string key in headers.Keys)
{
request.Headers.Add(key, headers[key]);
}
}
// Send the request and get the corresponding response data
HttpWebResponse response = await request.GetResponseAsync() as HttpWebResponse;
// until request.GetResponse() The program starts to send to the target web page Post request
Stream responseStream = response.GetResponseStream();
// Create a write stream
MemoryStream stream = new MemoryStream();
byte[] bArr = new byte[10240];
int size = await responseStream.ReadAsync(bArr, 0, (int)bArr.Length);
while (size > 0)
{
stream.Write(bArr, 0, size);
size = await responseStream.ReadAsync(bArr, 0, (int)bArr.Length);
}
stream.Seek(0, SeekOrigin.Begin);
responseStream.Close();
return stream;
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
#region HttpDownloadFile Download the file ( Callback based asynchronous )
/// <summary>
/// Download the file
/// </summary>
/// <param name="url"> Download the file url route </param>
/// <param name="cookie">cookie</param>
public static void HttpDownloadFileAsyncWithCallback(string url, HttpUtilAsyncState state = null, Action<object> callback = null, CookieContainer cookie = null, WebHeaderCollection headers = null)
{
try
{
if (state.State == 0)
{
// Set parameters
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "GET";
request.CookieContainer = cookie;
if (headers != null)
{
foreach (string key in headers.Keys)
{
request.Headers.Add(key, headers[key]);
}
}
// Send the request and get the corresponding response data
request.BeginGetResponse(asyncResult =>
{
HttpUtilAsyncState asyncState = asyncResult.AsyncState as HttpUtilAsyncState;
try
{
HttpWebResponse response = request.EndGetResponse(asyncResult) as HttpWebResponse;
asyncState.ResponseStream = response.GetResponseStream();
HttpDownloadFileAsyncWithCallback(null, asyncState, callback);
}
catch (Exception ex)
{
asyncState.Exception = ex;
asyncState.State = 2;
HttpDownloadFileAsyncWithCallback(null, asyncState, callback);
}
}, new HttpUtilAsyncState { Request = request, State = 1 });
return;
}
if (state.State == 1)
{
byte[] bArr = new byte[10240];
state.ResponseStream.BeginRead(bArr, 0, (int)bArr.Length, asyncResult =>
{
HttpUtilAsyncState asyncState = asyncResult.AsyncState as HttpUtilAsyncState;
try
{
int size = state.ResponseStream.EndRead(asyncResult);
if (size > 0)
{
state.Stream.Write(bArr, 0, size);
HttpDownloadFileAsyncWithCallback(null, asyncState, callback);
}
else
{
asyncState.State = 2;
HttpDownloadFileAsyncWithCallback(null, asyncState, callback);
}
}
catch (Exception ex)
{
asyncState.Exception = ex;
asyncState.State = 2;
HttpDownloadFileAsyncWithCallback(null, asyncState, callback);
}
}, state);
return;
}
if (state.State == 2)
{
if (state.Exception != null)
{
callback(state.Exception);
return;
}
else
{
state.Stream.Seek(0, SeekOrigin.Begin);
state.ResponseStream.Close();
callback(state.Stream);
return;
}
}
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
}
}
边栏推荐
- One bite of Stream(7)
- Click the button to return to the top smoothly
- How to set appium script startup parameters
- Spark related FAQ summary
- Oracle 19C datagruad replication standby rman-05535 ora-01275
- climb stairs
- 2787: calculate 24
- Pressing Ctrl will cause several key press messages
- Leetcode 1911. maximum subsequence alternating sum
- Build your own stock analysis system based on b\s architecture
猜你喜欢

Transport layer protocol parsing -- UDP and TCP

English grammar_ Demonstrative pronoun this / these / that / those

Cloud native observability tracking technology in the eyes of Baidu engineers

Let's make a nice monthly temperature map of China with ArcGIS

Five digital transformation strategies of B2B Enterprises

API data interface of A-share transaction data

Two methods of how to export asynchronous data
![[training Day6] game [mathematics]](/img/b2/09c752d789eead9a6b60f4b4b1d5d4.png)
[training Day6] game [mathematics]

PC port occupation release

ma.glasnost.orika. MappingException:No converter registered for conversion from Date to LocalDateTime
随机推荐
Failed to create a concurrent index, leaving an invalid index. How to find it
1. Mx6u-alpha development board (key input experiment)
[training Day10] silly [simulation] [greed]
Opengl rendering pipeline
2787: calculate 24
Cloud native observability tracking technology in the eyes of Baidu engineers
[sciter]: window communication
Baidu classic interview question - determine prime (how to optimize?)
Leetcode 1928. minimum cost of reaching the destination within the specified time
Experience of using dump file to reverse locate crash location
Guys, I have no problem running locally in diea, running on the server. What's wrong with the lack of CDC connection? The database IP can be pinged
Understand the domestic open source Magnolia license series agreement in simple terms
[learning notes] agc008
RESNET interpretation and 1 × 1 Introduction to convolution
What should Ali pay attention to during the interview? Personal account of Alibaba interns who passed five rounds of interviews
[training Day10] point [enumeration] [bidirectional linked list]
Shengbang security rushes to the scientific innovation board: Qianxin is its largest customer (55.87 million); Its three-year revenue is 460 million, net profit is 95.04 million, and R & D investment
Application layer - typical protocol analysis
Oracle 19C datagruad replication standby rman-05535 ora-01275
Preview and save pictures using uni app