문제

C# 2008

아래 코드를 사용하여 소프트폰에 로그인하고 있습니다.그러나 로그인 진행은 초기화해야 할 사항과 확인해야 할 사항이 많기 때문에 긴 프로세스입니다. 코드를 게시하는 데 시간이 오래 걸릴 수 있으므로 여기에는 몇 가지만 넣었습니다.

아래 코드에서는 각 확인을 수행하기 전에 취소 버튼 클릭 이벤트에서 CancelAsync가 호출된 경우 CancellationPending을 확인합니다.이 올바른지?또한 검사가 실패하면 CancelAsync를 호출하고 e.Cancel을 true로 설정합니다.

제가 여기서 사용한 방법이 가장 좋은 방법인지 알고 싶습니다.

어떤 조언이라도 감사드립니다.

private void bgwProcessLogin_DoWork(object sender, DoWorkEventArgs e)
    {   
        /*
         * Perform at test to see if the background worker has been
         * cancelled by the user before attemping to continue to login.
         * 
         * Cancel background worker on any failed attemp to login
         */

        // Start with cancel being false as to reset this if cancel has been set to true
        // in the cancel button.
        e.Cancel = false;

        NetworkingTest connection_test = new NetworkingTest();
        if (!this.bgwProcessLogin.CancellationPending)
        { 
            // Check local LAN or Wireless connection               
            if (!connection_test.IsNetworkConnected())
            {
                // Update label
                if (this.lblRegistering.InvokeRequired)
                {
                    this.lblRegistering.Invoke(new UpdateRegisterLabelDelegate(UpdateRegisterLabel), "No network connection");
                }
                else
                {
                    this.lblRegistering.Text = "No network connection";
                }
                // Failed attemp
                this.bgwProcessLogin.CancelAsync();
                e.Cancel = true;
                return;
            }
            // Report current progress
            this.bgwProcessLogin.ReportProgress(0, "Network connected");
        }
        else
        {
            // User cancelled 
            e.Cancel = true;
            return;
        }

        // Test if access to Server is available
        if (!this.bgwProcessLogin.CancellationPending)
        {
            if (!connection_test.IsSIPServerAvailable())
            {
                // Update label
                if (this.lblRegistering.InvokeRequired)
                {
                    this.lblRegistering.Invoke(new UpdateRegisterLabelDelegate(UpdateRegisterLabel), "Server unavailable");
                }
                else
                {
                    this.lblRegistering.Text = "Server unavailable";
                }
                // Failed attemp
                this.bgwProcessLogin.CancelAsync();
                e.Cancel = true;
                return;
            }
            // Report current progress
            this.bgwProcessLogin.ReportProgress(1, "Server available");
        }
        else
        {
            // User cancelled 
            e.Cancel = true;
            return;
        }
        .
        .
        .
}


 private void bgwProcessLogin_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {   
        // Check for any errors
        if (e.Error == null)
        {
            if (e.Cancelled)
            {
                // User cancelled login or login failed                
            }
            else
            {
                // Login completed successfully                
            }
        }
        else
        {
            // Something failed display error
            this.statusDisplay1.CallStatus = e.Error.Message;
        }
    }


 private void bgwProcessLogin_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        this.lblRegistering.Text = e.UserState.ToString();
    }

private void btnCancel_Click(object sender, EventArgs e)
    {
        // Cancel the logging in process
        this.bgwProcessLogin.CancelAsync();
        this.lblRegistering.Text = "Logged out";
}
도움이 되었습니까?

해결책

아마도 단 하나의 문제가 있을 수 있습니다.DoWork 이벤트 핸들러의 작업 중 하나가 오랫동안 지속되는 경우.이 경우 해당 작업이 완료된 후에만 보류 중인 작업을 중단할 수 있습니다.DoWork 이벤트의 모든 작업이 매우 오래 지속될 수 없는 경우(예: 5초 이하) 모두 괜찮습니다. 그러나 작업 중 하나가 오랫동안 지속될 수 있는 경우(예: 5분) 이 경우 사용자는 이 작업이 완료될 때까지 기다리세요.

DoWork에 오래 지속되는 작업이 포함된 경우 AbortableBackgroundWorker와 같은 것을 사용할 수 있습니다.이 같은:

public class AbortableBackgroundWorker : BackgroundWorker
{
    private Thread workerThread;

    protected override void OnDoWork(DoWorkEventArgs e)
    {
        workerThread = Thread.CurrentThread;
        try
        {
            base.OnDoWork(e);
        }
        catch (ThreadAbortException)
        {
            e.Cancel = true; //We must set Cancel property to true!
            Thread.ResetAbort(); //Prevents ThreadAbortException propagation
        }
    }


    public void Abort()
    {
        if (workerThread != null)
        {
            workerThread.Abort();
            workerThread = null;
        }
    }
}

이 경우 보류 중인 작업을 실제로 중단할 수 있지만 몇 가지 제한 사항도 있습니다. 관리되는 스레드 중단 및 일부 제한 사항에 대한 자세한 내용은 다음을 참조하세요. Rotor를 사용하여 ThreadAbortException의 깊이 연결).

추신InvokeRequired를 더 사용하기 쉬운 형식으로 래핑해야 한다는 Oliver의 의견에 동의합니다.

다른 팁

당신은 올바른 방법으로하고 있습니다. 스레드를 종료하거나 중단 할 수있는 스레드 멤버를 찾을 수 있지만 이와 같은 용도로 사용하고 싶지는 않습니다. 코드에 "취소 된"수표를 모두 갖는 것은 조금 이상하게 보이지만 스레드를 종료 할 때 정확히 제어 할 수 있습니다. 작업자 실을 "무례하게"중단하려면 스레드는 종료시기를 제어 할 수 없으며 상태가 손상 될 수 있습니다.

당신이 쓴 dowork () 함수 내에서 .... 표시된 두 개와 같이 동일한 구조의 얼마나 많은 작업이 오는지에 따라이 구조를 자체 방법으로 리팩토링하여 변경 부품을 매개 변수로 제공 할 수 있습니다.

또한이 수개 차가 IF-ELSE 브랜치는 출력 문자열을 두 배로 늘 렸습니다. 여기에서 stackoverflow 또는 웹에서 약간 검색하면이 배가를 달성하기위한 패턴을 보여 주어야합니다.

Evernything Evernything은 꽤 좋아 보입니다.

this.bgwprocesslogin.cancelasync ()를 호출 할 필요가없는 한 가지가 있습니다. 이 e.cancel = true를 설정할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top