主頁 > .NET開發 > 真?WPF 按鈕拖動和調整大小

真?WPF 按鈕拖動和調整大小

2020-09-10 09:58:19 .NET開發

真?WPF 按鈕拖動和調整大小

獨立觀察員 2020 年 8 月 29 日

手頭有個 Winform 程式,是使用動態生成按鈕,然后拖動、調整大小,以此來記錄一些坐標資料,最后保存坐標資料的,

在資料量(按鈕數量)比較小的時候是使用得挺愉快的,但是,當按鈕數上去之后,比如達到四五百個按鈕,那就比較痛苦了,具體來說就是,無論是移動視窗,還是拖動滾動條,或者是最小化視窗再還原,都會引起界面重繪,表現為按鈕一個接一個地出現,

經過實測,與電腦的性能和 GPU 都沒有關系,網上針對 Winform 這個問題的解決方案,比如開啟雙緩沖等,都大致嘗試了,并無任何起色,反而可能更糟,所以就像網友所說,這個要么不要在同一個界面上放置太多控制元件;要么使用 WPF,畢竟 WPF 采用的是 DirectX 作為底層繪圖引擎,而 Winform 則采用傳統的 GDI ,由于業務需求,不讓在界面上放置過多控制元件的方案不太可行,或者說暫未想到有什么變通的辦法,所以決定改版為 WPF 試試,

 

經過幾天的改造,原 Winform 版軟體的一小部分功能已改版為 WPF 版,而且成果喜人,同樣的按鈕數量,現在無論怎樣折騰,這幾百個按鈕就如同釘在了界面上一樣,不再能看到他們載入的程序了,在這個改造的程序中,我是將 Winform 版軟體中關于按鈕拖動和調整大小的代碼改造為 WPF 版的,聽上去挺簡單的,但是還是碰到了一些問題,比如 WPF 屏蔽了滑鼠左鍵的一些事件,需要額外處理一下,還有的就是關于坐標定位的一些問題了,下面將給出一些關鍵代碼,和大家相互交流學習一下,

 

首先,先上一道小菜,解決一下 WPF 按鈕控制元件(Button)中文字自動換行的問題,

不對,還是先看看 Demo 的界面結構吧:

 

其它控制元件和布局就不說了(最后會給出 Demo 地址),關鍵的是中間這個 ScrollViewer 包裹的 Canvas,我們生成的按鈕都是在這個 Canvas 上的,拖動和調整大小也是,Winform 的布局是依賴于坐標的,WPF 的布局控制元件則基本是不使用坐標定位的,甚至都不推薦指定大小,而只有 Canvas 布局控制元件保留了以坐標定位的模式,正好適合我們的需求(之前 Winform 版使用的是 Panel 控制元件),

可以看到里面我還注釋了一個 Button ,這個就是用來演示我們的 “小菜” 問題(按鈕文字自動換行)的,我們先把注釋放開,并且只保留其寬和高的設定:

 

可以看到當按鈕寬度窄于文本內容時,文本內容并不能進行自動換行,且 Button 控制元件并沒有相關屬性進行設定,解決方法就是在按鈕中添加 TextBlock 控制元件,然后設定其 TextWrapping 屬性,當然,這里我們不直接這樣寫,而是使用內容模板:

<Button Width="38" Height="75" ContentTemplate="{DynamicResource DataTemplateButtonWrap}">1A005</Button>

 

這個模板的資源放在 App.xaml 中:

<Application.Resources>
    <DataTemplate x:Key="DataTemplateButtonWrap" DataType="Button">
        <Grid>
            <TextBlock TextWrapping="Wrap" Text="{TemplateBinding Content}"></TextBlock>
        </Grid>
    </DataTemplate>
</Application.Resources>

 

TextBlock 中使用了 TemplateBinding 將 Button 的 Content “綁架” 到了自己的 Text 中,哈哈,看看效果:

 

至于后臺動態系結資源則是使用 SetResourceReference 方法,后面代碼里也有體現,

 

好了,小菜吃完了,開始吃主菜吧:

#region 成員

private Control _control;
private int _btnNum = 0;

#endregion

/// <summary>
/// 設定控制元件在Canvas容器中的位置;
/// </summary>
private void SetControlLocation(Control control, Point point)
{
    Canvas.SetLeft(control, point.X);
    Canvas.SetTop(control, point.Y);
}

/// <summary>
/// 添加按鈕
/// </summary>
private void AddBtnHandler()
{
    string btnContent = GetBtnContent();

    Button btn = new Button
    {
        Name = "btn" + btnContent,
        Content = "btn" + btnContent,
        Width = 80,
        Height = 20,
    };

    _control = btn;
    AddContorlToCanvas(_control);
    SetControlLocation(_control, new Point(163, 55));
}

/// <summary>
/// 添加控制元件到界面;
/// </summary>
/// <param name="control"></param>
private void AddContorlToCanvas(Control control)
{
    control.MouseDown += MyMouseDown;
    control.MouseLeave += MyMouseLeave;
    //_control.MouseMove += MyMouseMove;
    control.KeyDown += MyKeyDown;

    //解決滑鼠左鍵無法觸發 MouseDown 的問題;
    control.AddHandler(Button.MouseLeftButtonDownEvent, new MouseButtonEventHandler(MyMouseDown), true);
    control.AddHandler(Button.MouseMoveEvent, new MouseEventHandler(MyMouseMove), true);

    CanvasMain.Children.Add(control);

    if (control is Button)
    {
        //模板中設定按鈕文字換行(模板資源在App.xaml中);
        control.SetResourceReference(ContentTemplateProperty, "DataTemplateButtonWrap");
        _btnNum++;
    }
}

/// <summary>
/// 生成按鈕內容
/// </summary>
/// <returns></returns>
private string GetBtnContent()
{
    return (_btnNum + 1).ToString().PadLeft(3, '0');
}

/// <summary>
/// 洗掉按鈕
/// </summary>
private void DelBtnHandler()
{
    CanvasMain.Children.Remove(_control);
}

 

上面代碼是對按鈕生成、添加到界面的一些操作邏輯,每個方法都有注釋,具體的大家自己看看,這里就不在贅述了,其中 添加控制元件到界面 的方法 AddContorlToCanvas 中,給控制元件(本文指的是按鈕)添加了 MouseDown、MouseLeave、MouseMove、KeyDown 等滑鼠鍵盤事件,然后開頭說過,WPF 屏蔽了 Button 的滑鼠左鍵的一些事件,所以需要使用 AddHandler 進行處理,

 

下面來看看主菜中的精華:

#region 實作表單內的控制元件拖動

const int Band = 5;
const int BtnMinWidth = 10;
const int BtnMinHeight = 10;
private EnumMousePointPosition _enumMousePointPosition;
private Point _point; //記錄滑鼠上次位置;

#region btn按鈕拖動

/// <summary>
/// 滑鼠按下
/// </summary>
private void MyMouseDown(object sender, MouseEventArgs e)
{
    //選擇當前的按鈕
    Button button = (Button)sender;
    _control = button;
    //Point point = e.GetPosition(CanvasMain);

    //左鍵點擊按鈕后可按WSAD進行上下左右移動;
    if (e.LeftButton == MouseButtonState.Pressed)
    {
        button.KeyDown += new KeyEventHandler(MyKeyDown);
    }

    double left = Canvas.GetLeft(_control);
    double top = Canvas.GetTop(_control);

    //右鍵點擊按鈕可向選定方向生成新按鈕;
    if (e.RightButton == MouseButtonState.Pressed)
    {
        Button btn = new Button
        {
            Name = "btn" + GetBtnContent(), 
            Content = GetStrEndNumAddOne(button.Content.ToString())
        };

        CheckRepeat(btn.Content.ToString());

        btn.Width = _control.Width;
        btn.Height = _control.Height;

        if (rbUpper.IsChecked == true)//
        {
            int h = txtUpper.Text.Trim() == "" ? 0 : Convert.ToInt32(txtUpper.Text.Trim());
            SetControlLocation(btn, new Point(left, top - _control.Height - h));
        }
        if (rbLower.IsChecked == true)//
        {
            int h = txtLower.Text.Trim() == "" ? 0 : Convert.ToInt32(txtLower.Text.Trim());
            SetControlLocation(btn, new Point(left, top + _control.Height + h));
        }
        if (rbLeft.IsChecked == true)//
        {
            int w = txtLeft.Text.Trim() == "" ? 0 : Convert.ToInt32(txtLeft.Text.Trim());
            SetControlLocation(btn, new Point(left - _control.Width - w, top));
        }
        if (rbRight.IsChecked == true)//
        {
            int w = txtRight.Text.Trim() == "" ? 0 : Convert.ToInt32(txtRight.Text.Trim());
            SetControlLocation(btn, new Point(left + _control.Width + w, top));
        }

        _control = btn;
        AddContorlToCanvas(_control);
    }
    
    //TODO 中鍵點擊按鈕可進行資訊編輯;
}

/// <summary>
/// 檢查重復內容按鈕
/// </summary>
/// <param name="content"></param>
private void CheckRepeat(string content)
{
    foreach (Control c in CanvasMain.Children)
    {
        if (c is Button btn)
        {
            if (content == btn.Content.ToString())
            {
                MessageBox.Show("出現重復按鈕內容:" + content, "提示");
                return;
            }
        }
    }
}

/// <summary>
/// 獲取非純數字字串的數值加一結果;
/// </summary>
private string GetStrEndNumAddOne(string str)
{
    int numberIndex = 0; //數字部分的起始位置;
    int charIndex = 0;
    foreach (char tempchar in str.ToCharArray())
    {
        charIndex++;
        if (!char.IsNumber(tempchar))
        {
            numberIndex = charIndex;
        }
    }

    string prefix = str.Substring(0, numberIndex);
    string numberStrOrigin = str.Remove(0, numberIndex);
    string numberStrTemp = "";

    if (numberStrOrigin != "")
    {
        numberStrTemp = (Convert.ToInt32(numberStrOrigin) + 1).ToString();
    }

    string result = "";
    if (numberStrOrigin.Length <= numberStrTemp.Length)
    {
        result = prefix + numberStrTemp;
    }
    else
    {
        result = prefix + numberStrTemp.PadLeft(numberStrOrigin.Length, '0');
    }

    return result;
}

/// <summary>
/// 滑鼠離開
/// </summary>
private void MyMouseLeave(object sender, EventArgs e)
{
    _enumMousePointPosition = EnumMousePointPosition.MouseSizeNone;
    _control.Cursor = Cursors.Arrow;
}

/// <summary>
/// 滑鼠移動
/// </summary>
private void MyMouseMove(object sender, MouseEventArgs e)
{
    _control = (Control)sender;
    double left = Canvas.GetLeft(_control);
    double top = Canvas.GetTop(_control);
    Point point = e.GetPosition(CanvasMain);
    double height = _control.Height;
    double width = _control.Width;

    if (e.LeftButton == MouseButtonState.Pressed)
    {
        switch (_enumMousePointPosition)
        {
            case EnumMousePointPosition.MouseDrag:

                SetControlLocation(_control, new Point(left + point.X - _point.X, top + point.Y - _point.Y));

                break;

            case EnumMousePointPosition.MouseSizeBottom:

                height += point.Y - _point.Y;

                break;

            case EnumMousePointPosition.MouseSizeBottomRight:

                width += point.X - _point.X;
                height += point.Y - _point.Y;

                break;

            case EnumMousePointPosition.MouseSizeRight:

                width += point.X - _point.X;

                break;

            case EnumMousePointPosition.MouseSizeTop:

                SetControlLocation(_control, new Point(left, top + point.Y - _point.Y));
                height -= (point.Y - _point.Y);

                break;

            case EnumMousePointPosition.MouseSizeLeft:

                SetControlLocation(_control, new Point(left + point.X - _point.X, top));
                width -= (point.X - _point.X);

                break;

            case EnumMousePointPosition.MouseSizeBottomLeft:

                SetControlLocation(_control, new Point(left + point.X - _point.X, top));
                width -= (point.X - _point.X);
                height += point.Y - _point.Y;

                break;

            case EnumMousePointPosition.MouseSizeTopRight:

                SetControlLocation(_control, new Point(left, top + point.Y - _point.Y));
                width += (point.X - _point.X);
                height -= (point.Y - _point.Y);

                break;

            case EnumMousePointPosition.MouseSizeTopLeft:

                SetControlLocation(_control, new Point(left + point.X - _point.X, top + point.Y - _point.Y));
                width -= (point.X - _point.X);
                height -= (point.Y - _point.Y);

                break;

            default:

                break;
        }

        //記錄游標拖動到的當前點
        _point.X = point.X;
        _point.Y = point.Y;

        if (width < BtnMinWidth) width = BtnMinWidth;
        if (height < BtnMinHeight) height = BtnMinHeight;
        _control.Width = width;
        _control.Height = height;
    }
    else
    {
        _enumMousePointPosition = GetMousePointPosition(_control, e); //'判斷游標的位置狀態

        switch (_enumMousePointPosition) //'改變游標
        {
            case EnumMousePointPosition.MouseSizeNone:
                _control.Cursor = Cursors.Arrow;       //'箭頭
                break;

            case EnumMousePointPosition.MouseDrag:
                _control.Cursor = Cursors.SizeAll;     //'四方向
                break;

            case EnumMousePointPosition.MouseSizeBottom:
                _control.Cursor = Cursors.SizeNS;      //'南北
                break;

            case EnumMousePointPosition.MouseSizeTop:
                _control.Cursor = Cursors.SizeNS;      //'南北
                break;

            case EnumMousePointPosition.MouseSizeLeft:
                _control.Cursor = Cursors.SizeWE;      //'東西
                break;

            case EnumMousePointPosition.MouseSizeRight:
                _control.Cursor = Cursors.SizeWE;      //'東西
                break;

            case EnumMousePointPosition.MouseSizeBottomLeft:
                _control.Cursor = Cursors.SizeNESW;    //'東北到南西
                break;

            case EnumMousePointPosition.MouseSizeBottomRight:
                _control.Cursor = Cursors.SizeNWSE;    //'東南到西北
                break;

            case EnumMousePointPosition.MouseSizeTopLeft:
                _control.Cursor = Cursors.SizeNWSE;    //'東南到西北
                break;

            case EnumMousePointPosition.MouseSizeTopRight:
                _control.Cursor = Cursors.SizeNESW;    //'東北到南西
                break;

            default:
                break;
        }
    }
}

/// <summary>
/// 按鍵WSAD(上下左右)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MyKeyDown(object sender, KeyEventArgs e)
{
    double left = Canvas.GetLeft(_control);
    double top = Canvas.GetTop(_control);

    switch (e.Key)
    {
        case Key.W://
        {
            SetControlLocation(_control, new Point(left, top-1));
            break;
        }
        case Key.S://
        {
            SetControlLocation(_control, new Point(left, top+1));
            break;
        }
        case Key.A://
        {
            SetControlLocation(_control, new Point(left-1, top));
            break;
        }
        case Key.D://
        {
            SetControlLocation(_control, new Point(left+1, top));
            break;
        }
    }
}

#endregion 按鈕拖動

#region 滑鼠位置

/// <summary>
/// 滑鼠指標位置列舉;
/// </summary>
private enum EnumMousePointPosition
{
    /// <summary>
    ////// </summary>
    MouseSizeNone = 0,

    /// <summary>
    /// 拉伸右邊框
    /// </summary>
    MouseSizeRight = 1,

    /// <summary>
    /// 拉伸左邊框
    /// </summary>
    MouseSizeLeft = 2,

    /// <summary>
    /// 拉伸下邊框
    /// </summary>
    MouseSizeBottom = 3,

    /// <summary>
    /// 拉伸上邊框
    /// </summary>
    MouseSizeTop = 4,

    /// <summary>
    /// 拉伸左上角
    /// </summary>
    MouseSizeTopLeft = 5,

    /// <summary>
    /// 拉伸右上角
    /// </summary>
    MouseSizeTopRight = 6,

    /// <summary>
    /// 拉伸左下角
    /// </summary>
    MouseSizeBottomLeft = 7,

    /// <summary>
    /// 拉伸右下角
    /// </summary>
    MouseSizeBottomRight = 8,       

    /// <summary>
    /// 滑鼠拖動
    /// </summary>
    MouseDrag = 9
}

/// <summary>
/// 獲取滑鼠指標位置;
/// </summary>
/// <param name="control"></param>
/// <param name="e"></param>
/// <returns></returns>
private EnumMousePointPosition GetMousePointPosition(Control control, MouseEventArgs e)
{
    Size size = control.RenderSize;
    Point point = e.GetPosition(control);

    Point pointCanvas = e.GetPosition(CanvasMain);
    _point.X = pointCanvas.X;
    _point.Y = pointCanvas.Y;

    if ((point.X >= -1 * Band) | (point.X <= size.Width) | (point.Y >= -1 * Band) | (point.Y <= size.Height))
    {
        if (point.X < Band)
        {
            if (point.Y < Band)
            {
                return EnumMousePointPosition.MouseSizeTopLeft;
            }
            else
            {
                if (point.Y > -1 * Band + size.Height)
                {
                    return EnumMousePointPosition.MouseSizeBottomLeft;
                }
                else
                {
                    return EnumMousePointPosition.MouseSizeLeft;
                }
            }
        }
        else
        {
            if (point.X > -1 * Band + size.Width)
            {
                if (point.Y < Band)
                {
                    return EnumMousePointPosition.MouseSizeTopRight;
                }
                else
                {
                    if (point.Y > -1 * Band + size.Height)
                    {
                        return EnumMousePointPosition.MouseSizeBottomRight;
                    }
                    else
                    {
                        return EnumMousePointPosition.MouseSizeRight;
                    }
                }
            }
            else
            {
                if (point.Y < Band)
                {
                    return EnumMousePointPosition.MouseSizeTop;
                }
                else
                {
                    if (point.Y > -1 * Band + size.Height)
                    {
                        return EnumMousePointPosition.MouseSizeBottom;
                    }
                    else
                    {
                        return EnumMousePointPosition.MouseDrag;
                    }
                }
            }
        }
    }
    else
    {
        return EnumMousePointPosition.MouseSizeNone;
    }
}

#endregion 滑鼠位置

#endregion 實作表單內的控制元件拖動

 

俗話說,Talk is cheap,show me the code,那么既然代碼已給出,大家就直接批評指正唄,我也沒什么說的了(主要是肚子餓了),

給個效果圖吧:

 

動圖:

 

最后給出 Demo 地址:

https://gitee.com/dlgcy/Practice/tree/master/WPFPractice 

 

同步首發:

http://dlgcy.com/real-wpf-button-drag-and-resize/

微信公眾號

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/1742.html

標籤:WPF

上一篇:WPF仿win10加載影片 可用于loading加載

下一篇:WPF 使用漸變色在繪圖中靈活應用

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more